<template>
  <div class="ym-table" :style="customStyle">
    <!-- 表格操作栏 -->
    <div class="table-opts">
      <slot name="table-opts-left"/>
      <el-button v-if="tableOptsJudge('add')" type="primary" icon="el-icon-plus" size="small" @click="handleAddRowItem">
        新增
      </el-button>
      <el-button :loading="batchRejectLoading" v-if="tableOptsJudge('reject')" type="danger" size="small"
                 @click="handlesetStatus('reject')"
      >
        批量驳回
      </el-button>
      <el-button :loading="batchPassLoading" v-if="tableOptsJudge('pass')" type="primary" size="small"
                 @click="handlesetStatus('pass')"
      >
        批量通过
      </el-button>
      <Excel2Table
        v-if="tableOptsJudge('import')"
        :options="tableOpts.import"
        :apis="apis"
        @callback="handleTableImportCallback"
      />
      <a v-if="tableOptsJudge('download')" class="el-button el-button--small" :href="comDownloadUrl" download>
        <i class="el-icon-download"/>
        模板下载
      </a>
      <Table2Excel
        v-if="tableOptsJudge('export')"
        ref="table2Excel"
        :options="tableOpts.export"
        :thead-map="tableOpts.export.theadMap"
        :thead-props="tableOpts.export.theadProps"
        :base-api="tableOpts.export.baseApi"
        :data-name="tableOpts.export.dataName"
        :tfoot-data="tableOpts.export.tfootData"
        @click="handleExport()"
      />
      <!-- v-if="tableOptsJudge('batchDelete')" :disabled="delTooltipAble" -->
      <el-tooltip
        v-if="tableOptsJudge('batchDelete')"
        :disabled="delTooltipAble"
        popper-class="button-del-tooltip"
        effect="dark"
        content="请选择要删除的数据"
        placement="top"
      >
        <el-button
          v-if="selection"
          icon="el-icon-delete"
          size="small"
          :loading="batchDeleteLoading"
          :disabled="deleteLoading"
          @click.stop="handleBatchDelete()"
        >批量删除
        </el-button>
      </el-tooltip>
      <slot name="table-opts"/>
      <div class="table-opts-right">
        <slot name="table-opts-right"/>
      </div>
    </div>
    <!-- / 表格操作栏 -->
    <!-- 提示 -->
    <el-alert v-if="alertTip" type="warning" style="margin-bottom: 8px;padding: 0" show-icon :title="alertTip"
              :closable="false"
    />
    <!-- / 提示 -->
    <!-- Table表格 -->
    <el-table
      v-if="columns.length > 0"
      :id="'listTable' + tableKey"
      :ref="'table' + tableKey"
      :key="tableKey"
      v-loading="listLoadingConfig"
      :border="false"
      element-loading-text="Loading"
      highlight-current-row
      :stripe="false"
      height="100%"
      :data="listData"
      v-bind="$attrs"
      :style="{ width: '100%'}"
      v-on="$listeners"
      @header-click="headerClick"
      @selection-change="handleSelectionChange"

    >
      <el-table-column
        v-if="selection"
        type="selection"
        width="60"
        fixed="left"
        align="center"
        :selectable="selectableFunc"
      />
      <el-table-column
        v-if="index"
        label="序号"
        label-class-name="indexClass"
        min-width="80px"
        type="index"
        fixed="left"
        align="center"
      >
        <template slot-scope="scoped">
          {{ limit * (page - 1) + (scoped.$index + 1) }}
        </template>
      </el-table-column>
      <template>
        <el-table-column
          v-for="(item, i) in columns"
          :key="i"
          :label="item.label"
          :prop="item.prop"
          :sortable="item.sortable"
          :width="item.image ? '100px' : item.width"
          min-width="100px"
          max-width="300px"
          align="center"
          :fixed="item.fixed"
        >
          <!-- 主项 -->
          <template slot="header">
            <span v-html="item.label"/>
          </template>
          <!-- / 主项 -->
          <template v-if="!item.children" slot-scope="scope">
            <slot :name="item.prop" :row="scope.row">
              <div style="text-align: center" :class="{ link: item.type === 'link' }" @mouseover.stop="handleMouseOver">
                <el-tooltip
                  :disabled="!showOverflowTooltip"
                  popper-class="ym-table-tooltip"
                  placement="top"
                  effect="dark"
                >
                  <div
                    slot="content"
                    class="ym-table-tooltip-content"
                    v-html="item.method ? item.method(scope.row) : scope.row[item.prop]"
                  />
                  <div v-if="item.html" v-html="item.method ? item.method(scope.row) : scope.row[item.prop]"/>
                  <svg-icon
                    v-else-if="item.svgIcon"
                    class="type_icon"
                    :icon-class="item.method ? item.method(scope.row) : scope.row[item.prop]"
                  />
                  <div v-else-if="item.link">
                    <span @click="item.click?item.click(scope.row):changeHtml()" style="color: #3a8ee6;cursor: pointer">{{
                        item.method ? item.method(scope.row) : scope.row[item.prop]
                      }}</span>
                  </div>
                  <div v-else-if="item.image">
                    <span v-if="imageUrl(scope.row[item.prop]).length === 0">--</span>
                    <el-image
                      v-else
                      :scroll-container="'#listTable' + tableKey + ' .el-table__body-wrapper'"
                      :lazy="true"
                      style="width: 80px; height: 80px"
                      :src="imageUrl(scope.row[item.prop])[0]"
                      :preview-src-list="imageUrl(scope.row[item.prop])"
                    />
                  </div>
                  <div v-else-if="item.popover">
                    <el-popover trigger="hover" placement="top">
                      <div v-for="(option, i) in item.options" :key="i" v-show="option.vShow?option.vShow(scope.row):true" >
                        {{ option.label }}: {{ getValueByPath(scope.row, option.value) }}
                      </div>
                      <div slot="reference" class="name-wrapper">
                        <el-tag :type="item.tagType?item.tagType(scope.row):''" size="medium">{{ getValueByPath(scope.row, item.props)||item.default }}</el-tag>
                      </div>
                    </el-popover>
                  </div>
                  <div v-else-if="item.video">
                    <span v-if="scope.row[item.prop] === ''">--</span>
                    <video
                      v-else
                      controls
                      style="width: 150px; height: 80px"
                      :src="scope.row[item.prop]"
                    >
                      <source :src="scope.row[item.prop]" type="video/mp4">
                    </video>
                  </div>
                  <div v-else-if="item.switch">
                    <el-switch
                      v-model="scope.row[item.prop]"
                      :disabled="item.disabled ? item.disabled(scope.row) : false"
                      active-color="#13ce66"
                      inactive-color="#e2e2e3"
                      :active-value="item.activeValue"
                      :inactive-value="item.inactiveValue"
                      :active-text="item.activeText||''"
                      :inactive-text="item.inactiveText||''"
                      @change="item.switchChange && item.switchChange(scope.row)"
                    />
                  </div>
                  <div
                    v-else-if="item.method"
                    contenteditable="false"
                    :celleditable="item.input"
                    @dblclick="handleDbclickCell($event, item.input)"
                    @blur="handleCellBlur($event, scope.row, item)"
                  >
                    {{ item.method(scope.row) }}
                  </div>
                  <div v-else-if="item.options">
                    {{ renderOptions(scope.row[item.prop], item.options) }}
                  </div>
                  <div
                    v-else
                    contenteditable="false"
                    :celleditable="item.input"
                    @dblclick="handleDbclickCell($event, item.input)"
                    @blur="handleCellBlur($event, scope.row, item)"
                  >
                    {{ dealWithValue(scope.row[item.prop] || '--') }}
                  </div>
                </el-tooltip>
              </div>
            </slot>
          </template>
          <!-- 二级子项 -->
          <template v-if="item.children">
            <template v-for="children in item.children">
              <el-table-column
                :width="children.width || children.image ? '100px' : ''"
                :show-overflow-tooltip="true"
                align="center"
              >
                <template slot="header">
                  <span v-html="children.label"/>
                </template>
                <template slot-scope="{ row }">
                  <slot :name="children.prop" :row="row">
                    <div
                      style="text-align: center"
                      :class="{ link: children.type === 'link' }"
                      @mouseover.stop="handleMouseOver"
                    >
                      <el-tooltip
                        :disabled="!showOverflowTooltip"
                        popper-class="ym-table-tooltip"
                        placement="top"
                        effect="dark"
                      >
                        <div
                          slot="content"
                          class="ym-table-tooltip-content"
                          v-html="item.method ? item.method(row) : row[children.prop]"
                        />
                        <p v-if="children.html" v-html="row[children.prop]"/>
                        <div v-else-if="children.image">
                          <span v-if="imageUrl(row[children.prop]).length === 0">--</span>
                          <el-image
                            v-else
                            :scroll-container="'#listTable' + tableKey + ' .el-table__body-wrapper'"
                            :lazy="true"
                            style="width: 80px; height: 80px"
                            :src="imageUrl(row[children.prop])[0]"
                            :preview-src-list="imageUrl(row[children.prop])"
                          />
                        </div>
                        <p
                          v-else-if="children.method"
                          contenteditable="false"
                          :celleditable="children.input"
                          @dblclick="handleDbclickCell($event, children.input)"
                          @blur="handleCellBlur($event, row, children)"
                        >
                          {{ children.method(row) }}
                        </p>
                        <p v-else-if="children.options">
                          {{ renderOptions(row[children.prop], children.options) }}
                        </p>
                        <p
                          v-else
                          contenteditable="false"
                          :celleditable="children.input"
                          @dblclick="handleDbclickCell($event, children.input)"
                          @blur="handleCellBlur($event, row, children)"
                        >
                          {{ dealWithValue(row[children.prop] || '--') }}
                        </p>
                      </el-tooltip>
                    </div>
                  </slot>
                </template>
                <!-- 三级子项 -->
                <el-table-column
                  v-for="three in children.children"
                  :key="three.prop + i"
                  :width="three.width || three.image ? '100px' : ''"
                  :show-overflow-tooltip="true"
                  align="center"
                >
                  <template slot="header">
                    <span v-html="three.label"/>
                  </template>
                  <template slot-scope="{ row }">
                    <slot :name="three.prop" :row="row">
                      <div
                        style="text-align: center"
                        :class="{ link: three.type === 'link' }"
                        @mouseover.stop="handleMouseOver"
                      >
                        <el-tooltip
                          :disabled="!showOverflowTooltip"
                          popper-class="ym-table-tooltip"
                          placement="top"
                          effect="dark"
                        >
                          <div
                            slot="content"
                            class="ym-table-tooltip-content"
                            v-html="item.method ? item.method(row) : row[three.prop]"
                          />
                          <p v-if="three.html" v-html="row[three.prop]"/>
                          <div v-else-if="three.image">
                            <span v-if="imageUrl(row[three.prop]).length === 0">--</span>
                            <el-image
                              v-else
                              :scroll-container="'#listTable' + tableKey + ' .el-table__body-wrapper'"
                              :lazy="true"
                              style="width: 80px; height: 80px"
                              :src="imageUrl(row[three.prop])[0]"
                              :preview-src-list="imageUrl(row[three.prop])"
                            />
                          </div>
                          <p
                            v-else-if="three.method"
                            contenteditable="false"
                            :celleditable="three.input"
                            @dblclick="handleDbclickCell($event, three.input)"
                            @blur="handleCellBlur($event, row, three)"
                          >
                            {{ three.method(row) }}
                          </p>
                          <p v-else-if="three.options">
                            {{ renderOptions(row[three.prop], three.options) }}
                          </p>
                          <p
                            v-else
                            contenteditable="false"
                            :celleditable="three.input"
                            @dblclick="handleDbclickCell($event, three.input)"
                            @blur="handleCellBlur($event, row, three)"
                          >
                            {{ dealWithValue(row[three.prop] || '--') }}
                          </p>
                        </el-tooltip>
                      </div>
                    </slot>
                  </template>
                </el-table-column>
                <!-- / 三级子项 -->
              </el-table-column>
            </template>
          </template>
          <!-- / 二级子项 -->
        </el-table-column>
      </template>
      <!-- <template
        v-for="(name, slotIndex) in $slots"
      >
        <el-table-column :key="slotIndex" :label="name + ''">
          <slot :name="name" />
        </el-table-column>
      </template> -->
      <!-- 表格操作栏 ActionsOff 根据key操作匹配是否关闭按钮 -->
      <el-table-column
        v-if="tableRowsActions && tableRowsActions.length"
        label="操作"
        fixed="right"
        align="center"
        :width="tableRowsActions.length>=3?actionsWidth||'200': actionsWidth?actionsWidth: tableRowsActions.length*80"
      >
        <template slot-scope="{ row }">
          <template v-for="item in tableRowsActions">
            <el-button
              v-if="item.vIF ? item.vIF(row) : true"
              :key="item.key"
              :type="item.type || 'text'"
              :icon="item.icon"
              size="small"
              :disabled="item.disabled ? item.disabled(row) : false"
              :class="item.class"
              :style="item.style"
              @click="item.method ? item.method(row) : handleTableRowOpt(item.key, row)"
            >
              {{ item.setLabel ? item.setLabel(row) : item.label }}
            </el-button>
          </template>
        </template>
      </el-table-column>
      <!-- / 表格操作栏 -->
    </el-table>
    <slot name="table_footer" />
    <el-alert
      v-if="columns.length === 0"
      title="无表格配置数据"
      type="warning"
      center
      :closable="false"
      show-icon
      style="height: 100%"
    />
    <!-- /Table表格 -->
    <el-pagination
      v-if="columns.length > 0&&isPage"
      background
      layout="total, prev, pager, next, jumper"
      :page-size="limit"
      :page-sizes="[15, 30, 45, 60]"
      :current-page="page"
      :total="totalPage"
      @size-change="handleSizeChange"
      @current-change="handleCurrentChange"
    />
    <!-- 详情页 -->
    <TableDetail
      ref="tableDetail"
      v-model="tableDetailDrawerVisible"
      :detail-format="detailFormat"
      :detail-data="selectRow"
    />
    <!-- 编辑页 -->
    <TableEditor
      ref="tableEditor"
      v-model="tableEditorDrawerVisible"
      :edit-form="editForm"
      :edit-data="selectRow"
      :config="editConfig"
      :apis="apiParams"
      :opt-type="optType"
      @onValueChange="editValueChange"
      @callback="handleTableEditorCallback"
    >
      <template
        v-for="item in editForm[0] ? editForm[0].body.filter(c => c.custom) : []"
        v-slot:[item.prop]="scopeData"
      >
        <slot :name="item.prop" v-bind="scopeData"></slot>
      </template>
    </TableEditor>
  </div>
</template>

<script>
import request from '@/utils/request'

const Table2Excel = () => import('../Table2Excel')
const TableEditor = () => import('./tableEditor')
const TableDetail = () => import('./tableDetail')
export default {
  name: 'YMTable',
  components: {
    TableDetail,
    TableEditor,
    Table2Excel
  },
  props: {
    tableKey: {
      type: [String, Number],
      default: 1
    },
    loading: {
      type: Boolean,
      default: false
    },
    customLoading: {
      type: Boolean,
      default: true
    },
    // 自定义样式
    customStyle: {
      type: [String, Object],
      default: () => ({})
    },
    summarySpan: {
      type: Array,
      default: () => []
    },
    // 表格操作配置
    tableOptions: {
      type: Object,
      default: () => ({
        export: {
          show: false,
          theadMap: {
            type: Array,
            default: () => []
          },
          // 表格每列字段
          theadProps: {
            type: Array,
            default: () => {
            }
          },
          // 表格数据
          tableData: {
            type: Array,
            default: () => []
          },
          // 表格底部格式和数据，主要用于填写标注和格式
          tfootData: {
            type: Array,
            default: () => []
          },
          dataName: {
            type: String,
            default: 'excel.xlsx'
          }
        }
      })
    },
    // 是否有选择
    selection: {
      type: Boolean,
      default: false
    },
    // 用于处理是否可选
    selectableAction: {
      type: Function,
      default: () => true
    },
    // 是否有序号
    index: {
      type: Boolean,
      default: true
    },
    // 列表操作按钮
    rowsActions: {
      type: Array,
      default: () => []
    },
    actionsWidth: {
      type: Number,
      default: null
    },
    // 字段列表
    columns: {
      type: Array,
      default: () => []
    },
    // 编辑参数
    editForm: {
      type: Array,
      default: () => []
    },
    // 编辑框的配置
    editConfig: {
      type: Object,
      default: () => ({
        title: '',
        addTip: '',
        editTip: '',
        size: ''
      })
    },
    // 详情参数
    detailFormat: {
      type: Array,
      default: () => []
    },
    apis: {
      type: Object,
      default: () => {
      }
    },
    alertTip: {
      type: String,
      default: ''
    },
    isPage: {
      type: Boolean,
      default: true
    }
  },
  data() {
    return {
      optType: 'add',
      showOverflowTooltip: false,
      // 表格操作配置
      tableOpts: Object.assign(
        {},
        {
          hideAll: false,
          add: {
            show: false
          },
          batchDelete: {
            show: false
          },
          import: {
            show: false
          },
          export: {
            show: false
          },
          download: {
            show: false,
            url: '/static/template.xlsx'
          }
        },
        this.tableOptions
      ),
      // 表格行操作
      tableRowsActions: [
        // {
        //   key: 'bidden',
        //   label: '禁用',
        //   class: 'danger',
        //   method: (row) => {
        //   }
        // },
        // {
        //   key: 'detail',
        //   label: '详情',
        //   class: 'primary'
        // },
        // {
        //   key: 'edit',
        //   label: '编辑',
        //   class: 'primary'
        // },
        // {
        //   key: 'delete',
        //   label: '删除',
        //   class: 'danger'
        // }
      ],
      // 接口参数
      apiParams: Object.assign(
        {},
        {
          list: {
            url: '',
            params: {},
            dataParam: 'data'
          },
          preivew: {},
          import: {},
          edit: {}
        },
        this.apis
      ),
      // 选中的列
      selectionList: [],
      // 页码
      page: 1,
      limit: 15,
      totalPage: 0,
      isExport: false,
      // 表格数据
      listData: [],
      listLoading: false,
      tableDetailDrawerVisible: false,
      tableEditorDrawerVisible: false,
      selectRow: {},
      batchDeleteLoading: false,
      deleteLoading: false,
      searchParams: {},
      batchPassLoading: false,
      batchRejectLoading: false
    }
  },
  computed: {
    listLoadingConfig() {
      return this.listLoading && this.customLoading
    },
    removeHtml() {
      return (str) => {
        return str // .replace(/<[^>]+>/g, '')
      }
    },
    selectableFunc() {
      return (row, index) => {
        return this.selectableAction(row, index)
      }
    },
    // 批量删除是否给出提示
    delTooltipAble() {
      return !!this.selectionList.length
    },
    // 图片链接
    formatImageUrl() {
      return url => {
        if (!url) return []
        if (String(url) === '[]') {
          return ''
        } else if (String(url).indexOf('http') > -1) {
          return url
        } else {
          if (!url) return []
          // 判断url首字母是不是斜杆
          if (url.charAt(0) !== '/') {
            url = `/${url}`
          }
          const host = this.apiParams.imgApi || process.env.VUE_APP_BASE_IMG
          return `${host}${url}`
        }
      }
    },
    /**
     * 图片处理
     * @param {String|Array} url 图片链接
     */
    imageUrl() {
      return url => {
        if (!url) return []
        if (!Array.isArray(url)) {
          url = url.split(',')
          // console.log('🚀 表格显示的图片：', url)
        }
        if (String(url).includes('[]')) {
          return []
        } else if (Array.isArray(url)) {
          return url.map(item => this.formatImageUrl(item)) || []
        } else {
          if (String(url).includes('[') && String(url).includes(']') && !String(url).includes('[]')) {
            if (!url) return []
            const arr = JSON.parse(url)
            if (!Array.isArray(arr)) return []
            const result = arr.map(item => {
              if (typeof item === 'object') {
                return this.formatImageUrl(item.url)
              } else {
                return this.formatImageUrl(item)
              }
            })
            console.log('🚀 表格显示的图片：', result)
            return result
          } else if (String(url).includes('""')) {
            const temp = url.replace('""', '')
            return this.imageUrl(temp)
          } else {
            const arr = String(url).split(',')
            // 判断数据里面是否是空值
            if (arr.includes('')) {
              arr.splice(arr.indexOf(''), 1)
            }
            const result = arr.map(item => this.formatImageUrl(String(item).includes('[]') ? '' : item)) || []
            return result
          }
        }
      }
    },
    // 下载地址
    comDownloadUrl() {
      console.log('process.env.VUE_APP_BASE_DOWNLOAD', process.env.VUE_APP_BASE_DOWNLOAD)
      const prefix = this.tableOpts?.download?.prefix || (process.env.VUE_APP_BASE_DOWNLOAD !== undefined ? process.env.VUE_APP_BASE_DOWNLOAD : process.env.VUE_APP_BASE_PREFIX)
      return prefix + this.tableOpts.download.url
    },
    // 判断是否显示某个操作
    tableOptsJudge() {
      return item => {
        // 安全访问，确保 tableOpts[item] 存在
        const opt = this.tableOpts[item]
        if (!opt) {
          // console.warn(`操作项 "${item}" 不存在于 tableOpts 中`)
          return false
        }

        // 确保 show 属性存在，默认为 false
        const showOpt = opt.show !== undefined ? opt.show : false

        return showOpt && !this.tableOptions.hideAll
      }
    },
    // 渲染options选项
    renderOptions() {
      return (key, options) => {
        if (!options || !options.length) return key
        return (
          options.find(item => {
            if (typeof key === 'string') {
              return String(item.value) === String(key)
            } else if (typeof key === 'number') {
              return Number(item.value) === Number(key)
            } else {
              return item.value === key
            }
          })?.label || key
        )
      }
    },
    // 处理表格数值
    dealWithValue() {
      return value => {
        if (typeof value === 'number') {
          return parseFloat(Math.round(value * Math.pow(10, 2)) / Math.pow(10, 2))
        } else {
          return value
        }
      }
    }
  },
  watch: {
    loading(val) {
      this.listLoading = val
    },
    listData: {
      handler(val) {
        if (this.$refs['table' + this.tableKey]) {
          this.$nextTick(() => {
            if (this.$attrs['show-summary'] && this.summarySpan.length) {
              const static_tds = document.querySelectorAll('#listTable' + this.tableKey + ' .el-table__footer-wrapper tr>td')
              const fixed_tds = document.querySelectorAll('#listTable' + this.tableKey + ' .el-table__fixed-footer-wrapper tr>td')
              this.summarySpan.forEach((item, index) => {
                if (typeof item === 'object') {
                  static_tds[index].colSpan = item.span
                  static_tds[index].innerText = item.value
                  fixed_tds[index].colSpan = item.span
                } else {
                  if (item) {
                    static_tds[index].colSpan = item.span
                    fixed_tds[index].colSpan = item.span
                  } else {
                    static_tds[index].style.display = 'none'
                    fixed_tds[index].style.display = 'none'
                  }
                }
              })
            }

            this.$refs['table' + this.tableKey].doLayout()
            this.$refs['table' + this.tableKey].bodyWrapper.scrollTop = 0
          })
        }
      },
      immediate: true
    }
  },
  updated() {
    this.$nextTick(() => {
      this.$refs['table' + this.tableKey] && this.$refs['table' + this.tableKey].doLayout() // 解决表格行错位
    })
  },
  created() {
    console.log(this.$listeners, 842)
    console.log('$slots', this.$slots, this.$attrs)
    this._dealWidthRowsActions()
    if (this.apiParams?.list?.url && [undefined, true].includes(this.apiParams?.list?.init)) {
      this.getList(this.apiParams?.list?.Params)
    }
  },
  methods: {
    getValueByPath(obj, path) {
      if (!obj || !path) return ''
      let pathStr = ''
      if (typeof path === 'string') {
        pathStr = path
      } else if (Array.isArray(path) && path.length > 0) {
        pathStr = path[0]
      }
      if (!pathStr) return ''
      const keys = pathStr.split('.')
      let result = obj
      for (const key of keys) {
        if (result === null || result === undefined) return ''
        result = result[key]||'--'
      }
      return result !== undefined && result !== null ? result : ''
    },
    changeHtml() {
    },
    // contenteditable事件处理
    handleDbclickCell(event, bl) {
      bl && event.target.setAttribute('contenteditable', true)
    },
    handleCellBlur(event, row, cell) {
      const currentValue = { [cell.prop]: cell.validate ? cell.validate(event.target.innerText) : event.target.innerText }
      console.log()
      if (event.target.contentEditable === 'true') {
        this.$emit('onTableEdit', currentValue, Object.assign({}, row, currentValue))
      }
      event.target.setAttribute('contenteditable', false)
    },
    // 编辑表单内容变化
    editValueChange(val) {
      this.$emit('onEditValueChange', val)
    },
    handleMouseOver(row) {
      const cheight = row.fromElement?.childNodes[0]?.childNodes[0]?.clientHeight
      const sheight = row.fromElement?.childNodes[0]?.childNodes[0]?.scrollHeight
      this.showOverflowTooltip = cheight < sheight
    },
    // 处理行操作事项配置
    _dealWidthRowsActions() {
      // 将tableRowsActions中的对象和key值相同的对象合并
      if (this.rowsActions.length) {
        for (const iterator of this.rowsActions) {
          if (!this.tableRowsActions.length) {
            this.tableRowsActions = this.rowsActions
          } else {
            this.tableRowsActions = this.tableRowsActions.map(item => {
              if (item.key === iterator.key) {
                return Object.assign({}, item, iterator)
              } else {
                return item
              }
            })
          }
        }
      }
    },
    // 连续序号
    indexMethod(index) {
      const { limit, page } = this
      return limit * (page - 1) + index + 1
    },
    // 选择事件
    handleSelectionChange(val) {
      this.selectionList = val.map(item => item.id)
    },
    // 排序
    headerClick(column, event){
      this.$emit('headerClick',column, event)
    },
    // 表格导出
    handleExport() {
      this.isExport = true
      this.getList()
    },
    // 编辑回调
    handleTableEditorCallback(val) {
      this.getList(this.searchParams)
      this.$emit('onEditSubmit', val)
      this.apiParams?.add?.callback && this.apiParams?.add?.callback(val)
      this.apiParams?.edit?.callback && this.apiParams?.edit?.callback(val)
    },
    // 导入回调
    handleTableImportCallback(val) {
      this.handleCurrentChange(1)
      this.apiParams?.import?.callback && this.apiParams?.import?.callback(val)
    },
    // 分页事件
    handleSizeChange(val) {
      this.limit = val
      this.handleCurrentChange(1)
    },
    handleCurrentChange(val) {
      console.table('🚀  当前页码:', val)
      this.page = val
      this.getList(Object.assign({}, this.searchParams, { page: val }))
    },
    // 返回列表值
    _returnListData(response) {
      if (!this.apiParams.list.dataParam) return response.data
      const arr = this.apiParams.list.dataParam.split('.')
      arr.forEach(item => {
        response = response[item]
      })
      return response
    },
    // 返回接口返回值
    _returnResponse(response) {
      if (!this.apiParams.list.resultParam) return response
      const arr = this.apiParams.list.resultParam.split('.')
      arr.forEach(item => {
        response = response[item]
      })
      return response
    },
    // 获取表格数据
    getList(params) {
      return new Promise((resolve, reject) => {
        this.listLoading = true
        // 记录查询的参数
        if (params && Object.keys(params).length > 0) {
          this.searchParams = params
        }
        this._getList(params)
          .then(res => {
            this.listLoading = false
            const response = this._returnResponse(res)
            const listData = this._returnListData(res)
            if (this.$listeners.onResponse) {
              this.$emit('onResponse', response)
            }
            if (this.isExport) {
              console.log('🚀 导出数据：', listData)
              this.isExport = false
              this.$refs.table2Excel.exportToExcel(listData)
            } else {
              this.listData = listData
              this.totalPage = response.total
              resolve(res)
            }
          })
          .catch(error => {
            this.isExport = false
            this.listLoading = false
            reject(error)
          })
      })
    },
    // 列表查询接口
    _getList(SearchParams = {}) {
      if (SearchParams?.page) {
        this.page = SearchParams.page
      }
      console.log('🚀 查询列表参数：', SearchParams)
      // 获取接口传进来的初始值
      const { url, params = {}, method, limit = 'limit', page = 'page' } = this.apiParams.list
      const reqParams = {
        method: method || 'GET',
        url
      }
      if (SearchParams && Object.keys(SearchParams).length) {
        Object.assign(params, SearchParams)
      }
      // 根据方法的不同选择传递参数方式
      if (String(method).toLocaleLowerCase() === 'post') {
        Object.assign(reqParams, { data: params })
      } else {
        // page或者limit的字段可能不同，所以写成动态的
        Object.assign(params, this.isExport ? this.searchParams : {}, {
          [page]: this.isExport ? 1 : this.page,
          [limit]: this.isExport ? 99999 : this.limit
        })
        Object.assign(reqParams, { params })
      }
      return new Promise((resolve, reject) => {
        resolve(request(reqParams))
      })
    },
    // 批量驳回/通过
    handlesetStatus(type) {
      if (this.selectionList.length === 0) return this.$message.error('选择批量操作数据！')
      if (type === 'pass') {
        this.$confirm(`确定通过审核?`, '提示', {
          confirmButtonText: '确定',
          cancelButtonText: '取消',
          type: 'warning'
        }).then(() => {
          this.setStatus(type)
        })
      } else {
        this.$prompt('请输入原因', '提示', {
          confirmButtonText: '确定',
          cancelButtonText: '取消',
          inputPattern: /^\S+$/,
          inputErrorMessage: '请输入原因'
        }).then(({ value }) => {
          this.setStatus(type, value)
        })
      }
    },
    setStatus(type, value) {
      const ids = this.selectionList
      const paramsObj = this.apiParams[type]
      const paramKey = paramsObj?.params
      const status = paramsObj?.status
      const remark = paramsObj?.remark
      const statusValue = paramsObj?.statusValue
      let additionParams = ''
      if (paramsObj?.additionParams && paramsObj.additionParams.length) {
        additionParams = paramsObj?.additionParams
          .map(item => {
            return this.selectionList[item]
          })
          .join('/')
        additionParams = '/' + additionParams
      }
      if (!paramsObj?.url) {
        this.$message.error('url参数缺失！')
        return
      }
      let params = {
        url: paramsObj?.url + additionParams,
        method: paramsObj?.method
      }
      params = Object.assign({}, params, {
        data: {
          [paramKey || 'ids']: ids,
          [status]: statusValue,
          [remark]: value
        }
      })
      if (type === 'pass') {
        this.batchPassLoading = true
      } else {
        this.batchRejectLoading = true
      }
      request(params)
        .then(() => {
          this.batchPassLoading = false
          this.batchRejectLoading = false
          this.getList(this.searchParams)
          this.$message({
            type: 'success',
            message: '操作成功'
          })
        })
        .finally(() => {
          this.batchPassLoading = false
          this.batchRejectLoading = false
        })
    },
    // 批量删除
    handleBatchDelete() {
      if (!this.delTooltipAble) return false
      this._optDelete('batchDelete', this.selectionList)
    },
    /**
     * 删除方法逻辑处理
     * @param {delete/batchDelete} type
     * @param {*} row
     */
    _optDelete(type, row) {
      this.$confirm(type === 'delete' ? '确定删除该条数据吗？' : `数据删除后不可恢复，是否确认删除所选<b style="color:red;">${this.selectionList?.length}</b>条数据？`, '温馨提示', {
        type: 'warning',
        dangerouslyUseHTMLString: true
      }).then(() => {
        const ids = type === 'delete' ? row.id : this.selectionList.join(',')
        if (this.$listeners['delete']) {
          this.$emit('delete', ids)
        } else {
          const paramsObj = this.apiParams[type]
          const paramKey = paramsObj?.params
          let additionParams = ''
          if (paramsObj?.additionParams && paramsObj.additionParams.length) {
            additionParams = paramsObj?.additionParams
              .map(item => {
                return row[item]
              })
              .join('/')
            additionParams = '/' + additionParams
          }
          if (!paramsObj?.url) {
            this.$message.error('url参数缺失！')
            return
          }
          let params = {
            url: paramsObj?.url + additionParams,
            method: paramsObj?.method || 'delete'
          }
          params = Object.assign({}, params, {
            data: {
              [paramKey || 'id']: ids
            }
          })
          if (type === 'batchDelete') {
            this.batchDeleteLoading = true
          }
          this.deleteLoading = true
          request(params)
            .then(() => {
              this.deleteLoading = false
              this.batchDeleteLoading = false
              this.$message({
                type: 'success',
                message: '删除成功'
              })
              /**
               * 删除操作逻辑：
               * 1.通过listData判断当前页有多少条数据
               * 2.如果当前页减去删除的条数后数据大于0，则刷新当前页，否则减掉一页
               * 3.如果当前页为第一页，刷新当前页
               * 2.通过selectionList删除
               */
              const currentPageNum = this.listData.length
              const deleteNum = type === 'delete' ? 1 : this.selectionList?.length
              if (currentPageNum - deleteNum > 0) {
                this.handleCurrentChange(this.page)
              } else if (this.page > 1) {
                this.handleCurrentChange(this.page - 1)
              } else {
                this.handleCurrentChange(1)
              }
              paramsObj?.callback()
            })
            .finally(() => {
              this.deleteLoading = false
              this.batchDeleteLoading = false
            })
        }
      })
    },
    // 内部表格行操作
    handleTableRowOpt(key, row) {
      console.log('🚀 表格当前操作行：', key, row)
      this.selectRow = row
      if (key === 'edit') {
        // 编辑
        // this.$emit('edit', row)
        this.optType = 'edit'
        this.tableEditorDrawerVisible = true
      } else if (key === 'delete') {
        this._optDelete('delete', row)
      } else if (key === 'detail') {
        // 详情
        this.$emit('detail', row)
        this.tableDetailDrawerVisible = true
      } else if (key === 'preview') {
        // 查看
        this.tableEditorDrawerVisible = true
      } else {
        console.log('🚀 表格操作行:', row)
      }
    },
    // 新建
    handleAddRowItem() {
      if (this.tableOpts?.add?.method) {
        this.tableOpts?.add?.method()
      } else {
        this.selectRow = this.tableOpts?.add?.initData ? this.tableOpts?.add?.initData() : {}
        this.optType = 'add'
        this.tableEditorDrawerVisible = true
      }
    }
  }
}
</script>
<style></style>
<style lang="scss" scoped>
.ym-table {
  display: flex;
  flex: auto;
  flex-direction: column;

  padding: 0px 16px;

  border-radius: 4px;
  // background-color: #fff;
  .el-table {
    border-radius: 12px;
    overflow: hidden;
  }

  .el-table th.el-table__cell.is-leaf,
  .el-table thead.is-group th.el-table__cell {
    // background: #f5f7fa;
  }

  ::v-deep .el-table__fixed,
  ::v-deep .el-table__fixed-right {
    height: 100% !important;
  }

  ::v-deep .el-table th {
    background: #fff;
  }

  ::v-deep .el-table th .cell {
    color: #606266;

    font-weight: 500;
  }

  ::v-deep .el-table td .cell {
    display: -webkit-box;
    overflow: hidden;
    -webkit-box-orient: vertical;

    cursor: default;
    text-overflow: ellipsis;

    color: #606266;

    font-size: 14px;

    -webkit-line-clamp: 3;
  }

  .el-button--text {
    padding: 8px 0;

    font-size: 14px;
  }

  .link {
    cursor: pointer;
    text-decoration: underline;

    color: #409eff;

    &:hover {
      font-weight: 700;
    }
  }

  ::v-deep p img {
    max-width: 20px;
    max-height: 20px;
  }

  p[celleditable='true'] {
    min-width: 30px;
    min-height: 20px;
  }

  p[celleditable='true'][contenteditable='false'] {
    cursor: url('./dblclick.svg') 0 0,
    text;

    color: #409eff;
  }

  p[contenteditable='true'] {
    cursor: url('./cursoredit.svg') 0 0,
    text;

    border: 1px solid #409eff;
    // overflow-x: auto;
    border-radius: 4px;
    // white-space: nowrap;
  }
}

::v-deep.ym-table-tooltip {
  &-content {
    overflow-y: auto;

    max-height: 90vh;

    video,
    img {
      max-width: 100% !important;
    }
  }
}

.table-opts {
  padding-bottom: 12px;

  &-right {
    float: right;

    line-height: 32px;
  }

  .el-button {
    margin-right: 10px;
    padding: 8px 15px;

    font-size: 14px;

    & + .el-button {
      margin-left: 0;
    }
  }
}

.danger {
  color: #f56c6c;
}

::v-deep.el-button--text:hover span {
  font-weight: 700;
}

.ym-table-tooltip {
  overflow: hidden;

  height: 0px;

  text-overflow: ellipsis;
}
</style>
<style lang="scss">
.button-del-tooltip.el-tooltip__popper[x-placement^='top'] .popper__arrow,
.button-del-tooltip.el-tooltip__popper[x-placement^='top'] .popper__arrow:after {
  border-top-color: #f56c6c !important;
}

.el-tooltip__popper.is-dark.button-del-tooltip {
  background-color: #f56c6c;
}

/* el-image 加载前展示内容 */
.el-image__placeholder {
  width: 100%;
  height: 100%;

  background: url('../../assets/loading.gif') no-repeat;
  background-size: 100% 100%;
}

.el-table--border,
.el-table--group {
  border: none;
}

.el-table--border .el-table__cell,
.el-table__body-wrapper .el-table--border.is-scrolling-left ~ .el-table__fixed {
  border-right: 0;
}

.el-table__empty-block {
  width: 100% !important;
}

.el-pagination.is-background .el-pager li:not(.disabled).active {
  background-color: #fff;
  border-radius: 4px 4px 4px 4px;
  border: 1px solid #0663B7;
  color: #0663B7;
}

</style>
