<template>
  <div class="kyb-table" :class="autoContent && showTypeInner !== 'grad' ? '' : 'fit column'">
    <div class="kyb-table-header line_b" v-if="showToolbar">
      <slot name="top">
        <template v-if="toolbarList.length">
        <kyb-toolbar :items="toolbarList">
          <template #query="{isVisble}">
            <input
              :style="{ visibility: isVisble ? 'visible' : 'hidden' }"
              v-model="filter.___keyword"
              outlined
              dense
              placeholder="输入关键字查询"
              class="q-mr-xs"
              @input="
                filter.pageNo = 1
                query()
              "
            />
          </template>
          <template #save="{isVisble}">
            <!-- 保存 -->
            <q-btn
              :style="{ visibility: isVisble ? 'visible' : 'hidden' }"
              :icon="isEdit ? 'lock_open' : 'lock'"
              title="编辑"
              dense
              flat
              :color="isEdit ? 'primary' : 'negative'"
              @click="isEdit = !isEdit"
            />
          </template>
          <template #add="{item,isVisble}">
            <q-btn
              :style="{ visibility: isVisble ? 'visible' : 'hidden' }"
              :icon="isEdit ? 'add' : ''"
              :title="isEdit ? '添加' : '请解锁后操作'"
              color="primary"
              dense
              flat
              @click="item.click ? item.click() : addItem()"
              v-if="isEdit"
            >
              <q-tooltip>添加新数据</q-tooltip>
            </q-btn>
          </template>
        </kyb-toolbar>
        </template>
      </slot>
      <slot name="condition">
        <kyb-table-condition :mdata="kybMdata" :conditions="conditions" v-model="filter"></kyb-table-condition>
      </slot>
    </div>
    <!-- 无数据展示 -->
    <div v-if="(showTypeInner === 'card' || showTypeInner === 'table') && queryData.totalNum === 0" class="column fit flex-center col">
      <q-icon name="cloud_queue" color="grey-4" size="6em" />
      <div class="text-grey-4 text-h3 q-pa-md">无数据</div>
    </div>
    <div v-if="showTypeInner === 'table'" class="q-pa-xs full-width col">
      <q-table v-if="queryData.totalNum !== 0" :columns="computedCols" :data="queryData.items" :row-key="itemKey" hide-bottom flat :bordered="false" separator="cell" :pagination="pagination"
        class="full-height"
        :table-header-class="tableHeaderClass?tableHeaderClass:null"
        :table-header-style="tableHeaderStyle?tableHeaderStyle:null"
        :table-style="tableStyle?tableStyle:null"
        :table-class="tableClass?tableClass:'full-height'">
        <template #body="props">
          <q-tr :props="props">
            <template v-for="(col, index) in props.cols">
              <q-td :key="col.name" :props="props">
                <slot :name="`col-${col.name}`">
                <div v-if="col.inputType === 'file'">
                  <q-avatar v-if="getFieldValue(props.row, col)">
                    <img :src="__genImgUrlServiceFile(getFieldValue(props.row, col))" />
                  </q-avatar>
                </div>
                <div class="q-gutter-sm" v-else-if="col.name === '__operator_group'">
                  <template v-for="operation in col.operations">
                    <q-btn
                      v-if="operation.enable === undefined || (typeof operation.enable === 'function' ? operation.enable(props.row) : operation.enable)"
                      v-close-popup
                      dense
                      :key="operation.name"
                      :label="$t(operation.title || operation.name)"
                      :icon="operation.icon"
                      :color="operation.color"
                      @click="operation.click && operation.click(props.row, operation)"
                    >
                    </q-btn>
                  </template>
                </div>
                <template v-else>
                  <div :class="col.formatClass ? col.formatClass(getFieldValue(props.row, col),col,props.row) : ''" :style="col.formatStyle">
                    {{ col.format ? col.format(getFieldValue(props.row, col)) : getFieldValue(props.row, col, true) }}
                  </div>
                </template>
                </slot>
              </q-td>
            </template>
          </q-tr>
        </template>
      </q-table>
    </div>

    <div v-if="showTypeInner === 'card' && (!canUsePager || queryData.totalNum > 0)" class="relative-position col scroll q-pa-xs">
      <kyb-table-card-list
        :query-data="queryData"
        @itemClick="itemClick ? itemClick($event) : showForm($event)"
        :item-menu-list="itemMenuList"
        v-bind="viewFields"
      >
        <template #item-body="{item, index}">
          <slot name="item-body-card" v-bind="{ item, index }">
            <template v-if="viewFields">
              <q-item-label v-if="viewFields.titleField" class="ellipsis">{{ getFieldValue(item, viewFields.titleField) }}</q-item-label>
              <template v-for="(field, index) in viewFields.descFields">
                <q-item-label caption lines="2" :key="index" class="row" :class="field.color ? 'text-' + field.color : ''">
                  <span v-if="!(typeof field === 'object' && field.disableLabel)">{{ getFieldTitle(field) }}:</span>
                  <span
                    class="col ellipsis"
                    v-html="field.format ? field.format(getFieldValue(item, field)) : getFieldValue(item, field, true)"
                  ></span>
                </q-item-label>
              </template>
            </template>
          </slot>
        </template>
        <template #item="{item, index}">
          <slot name="item-card" v-bind="{ item, index }"></slot>
        </template>
        <template #item-avatar="{item}">
          <slot name="item-avatar-card" v-bind="{ item }">
            <template v-if="viewFields.avatarField && getField(viewFields.avatarField) && getFieldValue(item, getField(viewFields.avatarField))">
              <q-avatar v-if="getField(viewFields.avatarField).inputType === 'file'">
                <img :src="__genImgUrlServiceFile(getFieldValue(item, getField(viewFields.avatarField)))" />
              </q-avatar>
              <q-avatar v-else
                    :color="mdata.itemMap['canUse']&&!item.canUse?'grey-6': item.avatarColor || viewFields.avatarColor || 'primary'"
                    text-color="white">
                {{getFieldValue(viewFields.avatarField)}}
              </q-avatar>
            </template>
          </slot>
        </template>
        <template #item-append="{item, index}">
          <slot name="item-append-card" v-bind="{ item, index }"></slot>
        </template>
        <template #item-menu="{item}">
          <slot name="item-menu-card" v-bind="{ item }"></slot>
        </template>
      </kyb-table-card-list>
    </div>
    <div v-if="showTypeInner === 'grad'" class="kyb-table-content relative-position no-scroll">
      <div class="absolute top_right bg-light-0 no-scroll column" v-bind:style="{ left: topRightSLeft + 'px' }">
        <!--头部-->
        <div class="row table-row header">
          <div
            v-for="item in mdata.items"
            :key="item._id"
            class="table-call text-center text-weight-bold ellipsis"
            v-show="item.$selected"
            @click="sortByHeader(item)"
            :title="item.name"
            v-resize="{ resizeType: 'e' }"
          >
            <q-icon v-if="filter.orderBy === item.name" color="primary" :name="filter.orderByAsc ? 'expand_less' : 'expand_more'"></q-icon>
            <span v-text="item.title"></span>
            <q-resize-observer @resize="onResizeHeader($event, item)" />
          </div>
        </div>
        <!--快速过滤和添加-->
        <div class="row table-row">
          <div
            v-for="item in mdata.items"
            :key="item._id"
            class="table-call"
            :style="{ width: item.$width + 'px' }"
            v-show="item.$selected"
            :title="item.name + item.$width"
          >
            <input
              outlined
              dense
              v-model="newItem[item.name]"
              :placeholder="(isEdit && showAddRow ? '' : '过滤:') + item.title"
              class="fit text-primary"
              @clear="quickInput(item.name)"
              @input="quickInput(item.name)"
              clearable
            />
          </div>
        </div>
      </div>
      <div class="absolute down_left no-scroll" :style="{ top: downLeftSTop + 'px' }">
        <div v-for="item in queryData.items" :key="item._id" class="row" :class="item.$selected ? 'bg-light-0' : ''">
          <q-icon
            :name="item.$selected ? 'check_box' : 'check_box_outline_blank'"
            @click="
              item.$selected = !item.$selected
              selectItem(item)
            "
            :class="item.$selected ? 'text-primary' : ''"
            class="table-call"
          ></q-icon>
          <q-icon :name="isEdit ? 'clear' : ''" :disable="!isEdit" color="negative" @click="del(item._id)" class="table-call">
            <q-tooltip> <span v-if="!isEdit">解锁后，</span>删除该条数据 </q-tooltip>
          </q-icon>
          <q-icon name="menu" @click="showForm(item)" class="table-call right">
            <q-tooltip>修改该条数据</q-tooltip>
          </q-icon>
        </div>
      </div>
      <div class="absolute down_right scroll" @scroll.passive="contentScroll" :style="{ top: centerTop + 'px', left: centerLeft + 'px' }">
        <div v-if="queryData.totalNum === 0" class="column flex-center fit">
          <q-icon name="cloud_queue" color="grey-4" size="6em" />
          <div class="text-grey-4 text-h3 q-pa-md">无数据</div>
        </div>
        <!--内容-->
        <div class="column" style="flex-grow:1">
          <div v-for="item in queryData.items" :key="item._id" class="row table-row" :class="item.$selected ? 'bg-light-0' : ''">
            <div
              v-for="header in mdata.items"
              :key="header._id"
              :style="{ width: header.$width + 'px' }"
              :class="'table-call ' + header.type + ' ' + (selectedCell.hid === header._id && selectedCell._id === item._id ? 'selected' : '')"
              @click="selectCell(header, item)"
              v-show="header.$selected"
            >
              <q-icon
                v-if="header.type === 'boolean'"
                :color="item[header.name] ? 'primary' : 'grey-8'"
                @click="saveCell(header, item)"
                class="fit"
                :name="item[header.name] ? 'check_circle_outline' : 'clear'"
              ></q-icon>
              <div class="fit ellipsis" @click="saveCell(header, item)" :title="item[header.name]" v-text="item[header.name]" v-else></div>
            </div>
          </div>
        </div>
      </div>
      <!--覆盖着其他几个兄弟层的上面-->
      <div class="absolute top_left bg-light-0 no-scroll">
        <div class="row justify-center">
          <div class="table-call" v-if="selectModelInner !== 'more'"></div>
          <q-icon
            v-if="selectModelInner === 'more'"
            :name="queryData.selectAll ? 'check_box' : 'check_box_outline_blank'"
            @click="
              queryData.selectAll = !queryData.selectAll
              selectAll()
            "
            toggle-indeterminate
            :class="queryData.selectAll ? 'text-primary' : ''"
            class="table-call"
          >
            <q-tooltip>
              <span v-text="queryData.selectAll ? '取消' : ''"></span>全选当前列表的 <span v-text="queryData.items.length"></span>数据
            </q-tooltip>
          </q-icon>

          <q-icon
            :name="isEdit ? 'clear' : ''"
            v-bind:title="isEdit ? '删除' : '请解锁后操作'"
            color="negative"
            @click="delMore"
            class="table-call"
            :disable="!isEdit"
          >
            <q-tooltip> <span v-if="!isEdit">解锁后，</span>删除多条数据 </q-tooltip>
          </q-icon>

          <q-icon name="view_column" @click="headerFilter.show = true" class="table-call right" title="过滤栏位">
            <q-tooltip>单击过滤显示的栏位</q-tooltip>
          </q-icon>
        </div>
        <div class="row">
          <q-icon name="filter_list" class="table-call btn-con" title="过滤"></q-icon>
          <div class="table-call"></div>
          <q-icon name="cancel" @click="quickInputClear()" class="table-call btn-con right"></q-icon>
        </div>
      </div>
    </div>

    <!--分页-->
    <div
      class="kyb-table-footer"
      :class="autoContent && showTypeInner !== 'grad' ? '' : 'bg-grey-4'"
      v-if="canUsePager && queryData && queryData.items && queryData.items.length > 0"
    >
      <kyb-page
        :total-num="queryData.totalNum"
        :page-no="filter.pageNo"
        :page-size="filter.pageSize"
        @select-page="
          filter.pageNo = $event.pageNo
          filter.pageSize = $event.pageSize
          query()
        "
      />
    </div>

    <!--弹出窗口-->
    <!--选择栏位-->
    <q-dialog v-model="headerFilter.show" transition-show="scale" transition-hide="scale">
      <q-card class="no-scroll">
        <q-card-section class="bg-grey-5">
          <span class="text-h6">栏位过滤</span>
          <q-checkbox
            class="col-4"
            title="全选"
            color="neutral"
            keep-color
            label="全选"
            @input="selectAllHeader()"
            v-model="headerFilter.selectAll"
          ></q-checkbox>
          <input class="col-8" v-model="headerFilter.kerword" />
        </q-card-section>
        <q-separator />
        <q-card-section style="max-height: 50vh;padding:0" class="scroll">
          <div class="list" v-if="mdata.items">
            <div class="column q-pa-sm item" :class="item.$selected ? 'selected' : ''" v-for="item in mdata.items" :key="item._id">
              <q-checkbox :label="item.name + ' (' + item.title + ')'" v-model="item.$selected"></q-checkbox>
            </div>
          </div>
        </q-card-section>
        <q-separator />
        <q-card-actions align="right" class="bg-grey-3">
          <q-btn outline label="取消" color="grey-7" @click="headerFilter.show = false" />
        </q-card-actions>
      </q-card>
    </q-dialog>

    <!--transition-show="scale"-->
    <!--transition-hide="flip-left"-->
    <!-- 保存或修改表单 -->
    <q-dialog
      v-model="showSaveFormWin"
      transition-show="scale"
      transition-hide="scale"
      class="bg-white"
      @input="!showSaveFormWin && Object.assign(form, $$form)"
      persistent
    >
      <kyb-form
        class="bg-white"
        :entity="entity"
        :kyb-is-edit="form.isEdit"
        :kyb-can-edit="form.canEdit"
        :include-field="detailIncludeField"
        :exclude-field="detailExcludeField"
        :readonly-fields="detailReadonlyFields"
        :kyb-mdata="mdata"
        :format-mdata="detailFormatMdata"
        :is-add="form.isAdd"
        :entity-data-id="editItem ? editItem._id : null"
        v-model="editItem"
        @save-before="saveBefore"
        @save-after="saveAfter"
        @item-change="onFormItemChange"
        @item-blur="onFormItemBlur"
        style="max-width: 500px;"
        :style="form.style"
      >
        <template #form-item-title="item">
          <slot name="save-form-item-title" v-bind="item"></slot>
        </template>
        <template #top-right>
          <q-btn flat v-close-popup size="md" icon="close" />
        </template>
         <template #input="{item,group,fdata}">
          <slot name="form-item-input" v-bind="{item,group,fdata}"></slot>
        </template>
        <template #form-item-input-linkEntity="{item, group, mdata, fdata, props}">
          <slot name="form-item-input-linkEntity" v-bind="{item, group, mdata, fdata, props}"></slot>
        </template>
      </kyb-form>
    </q-dialog>
    <q-dialog v-model="importDataWin" transition-show="scale" transition-hide="scale">
      <q-card class>
        <q-bar>
          <q-icon name="vertical_align_top" />
          <div>导入数据</div>
          <q-space />
          <q-btn dense flat round icon="close" v-close-popup>
            <q-tooltip>关闭</q-tooltip>
          </q-btn>
        </q-bar>
        <slot name="import-body">
          <kyb-import-data :entity="entity" style="max-width: 500px;" />
        </slot>
      </q-card>
    </q-dialog>

    <slot name="extends"></slot>
  </div>
</template>

<script>
import _ from 'underscore'
import { dom, extend, date } from 'quasar'
import kybTableToolbar from './kyb-table-toolbar.js'
import KybMdata from '../kyb-mdata.js'
import KybTableCardList from './kyb-table-card-list'
import KybTableCondition from './kyb-table-condition'
// eslint-disable-next-line no-unused-vars
const { css, height, width, offset } = dom

let cellSize = 36

let obj = {
  name: 'kyb-table',
  mixins: [KybMdata],
  components: { KybTableCardList, KybTableCondition },
  model: {
    prop: 'value',
    event: 'input'
  },
  props: {
    // 设置元数据
    kybMdata: {
      type: Object,
      default: () => {
        return {}
      }
    },
    tableHeaderStyle: Object,
    tableHeaderClass: Array,
    tableStyle: Object,
    tableClass: Array,
    // 选择方式，more：为多选，默认单选
    selectModel: String,
    value: Object,
    // 显示方式，table：表格，card：卡片
    showType: {
      type: String,
      default: 'table'
    },
    showToolbar: {
      type: Boolean,
      default: true
    },
    itemKey: {
      type: String,
      default: '_id'
    },
    autoContent: Boolean,
    queryUrl: String,
    queryFilter: {
      type: Object,
      default: function() {
        return {}
      }
    },
    autoLoad: {
      type: Boolean,
      default: true
    },
    // 已选中的对象
    selectedMap: {
      type: Object,
      default: function() {
        return {}
      }
    },
    pageSize: Number,
    canUsePager: {
      type: Boolean,
      default: true
    },
    // 格式化数据
    formatData: Function,
    formatMdata: Function,
    toolbarExt: {
      type: Array,
      default: () => {
        return ['query', 'filter', 'refresh', 'import', 'export', 'showType', 'save', 'add']
      }
    },
    conditions: Array,
    /**
     * descFields 描述字段
     * titleField 标题字段 默认 title
     * avatarField 头像字段
     * itemMenuExt 卡片模式 菜单
     */
    viewFields: {
      type: Object
    },
    keyword: String,
    keywordFields: {
      type: Array,
      default: () => {
        return []
      }
    },
    itemClick: Function,
    kybIsEdit: Boolean,
    canEdit: {
      type: Boolean,
      default: true
    },
    tableShowField: Array,
    detailIncludeField: Array,
    detailExcludeField: {
      type: Array,
      default: () => {
        return ['_id', 'createTime', 'creator']
      }
    },
    detailReadonlyFields: Array,
    detailInitData: Object,
    detailFormatMdata: Function,
    form: {
      type: Object,
      default() {
        return {
          canEdit: this.canEdit,
          isEdit: this.kybIsEdit
        }
      }
    }
  },
  data: function() {
    let d = {
      selectedCell: {},
      filter: {
        pageNo: 1,
        pageSize: this.pageSize || 20,
        ___keyword: this.keyword || '',
        ___keyword_field: '_id',
        ...this.queryFilter
      },
      headerFilter: { show: false, keyword: '', selectAll: false },
      showAddRow: false,
      showSaveFormWin: false,
      showTypeInner: this.showType,
      isEdit: this.kybIsEdit,
      mdata: {},
      headers: [],
      keywords: '',
      newItem: {}, // 添加1行
      editItem: {}, // 表单方式编辑1行
      formIsAdd: false, // 确定是添加或修改数据
      formIsEdit: this.kybIsEdit,
      queryData: this.value || {
        pageNo: 1,
        pageSize: 20,
        selectAll: false,
        selectCount: 0,
        items: []
      },
      selectModelInner: this.selectModel ? this.selectModel : 'more',
      selectedMapInner: this.selectedMap ? this.selectedMap : {},
      // style
      centerTop: cellSize * 2,
      centerLeft: cellSize * 3,
      downLeftSTop: cellSize * 2 + 1,
      topRightSLeft: cellSize * 3,
      exportUrl: '',
      importDataWin: false,
      itemMenuMap: {
        edit: {
          icon: 'edit',
          name: 'edit',
          color: 'primary',
          isEdit: true,
          click: (item, menu, index) => this.showForm(item, undefined, true)
        },
        delete: {
          icon: 'clear',
          name: 'delete',
          color: 'negative',
          isEdit: true,
          click: (item, menu, index) => this.del(item[this.itemKey], index)
        }
      },
      itemMenuList: []
    }
    return d
  },
  computed: {
    exportDataUrl() {
      let url = this.exportUrl + '?1=1'
      Object.keys(this.filter).forEach(v => {
        url += `&${encodeURIComponent(v)}=${encodeURIComponent(this.filter[v])}`
      })
      return url
    },
    mdataMap() {
      return this.mdata.items.reduce((result, item) => {
        result[item.name] = item
        return result
      }, {})
    },
    // 初始化 工具栏
    toolbarList() {
      return kybTableToolbar({
        kybTable: this,
        toolbarExt: this.toolbarExt
      }).toolbarList.filter(item => {
        return item.enable === undefined || (typeof item.enable === 'function' ? item.enable() : item.enable)
      })
    },
    computedCols() {
      let cols = []
      if (this.tableShowField && this.tableShowField.length) {
        this.mdata.items &&
          (cols = this.mdata.items.filter(item => {
            return this.tableShowField.indexOf(item.name) !== -1
          }))
      } else if (this.viewFields) {
        const viewFields = []
        if (this.viewFields.avatarField) {
          viewFields.push(typeof this.viewFields.avatarField === 'object' ? this.viewFields.avatarField : { name: this.viewFields.avatarField, headerStyle: 'width: 64px' })
        }
        if (this.viewFields.titleField) {
          const field = typeof this.viewFields.titleField === 'object' ? this.viewFields.titleField : { name: this.viewFields.titleField }
          if (viewFields.length === 0 || viewFields.length && viewFields[0].name !== field.name) {
            viewFields.push(field)
          }
        }
        if (this.viewFields.descFields) {
          this.viewFields.descFields.forEach(field => {
            viewFields.push(typeof field === 'object' ? field : { name: field })
          })
        }
        cols = viewFields.filter(field => {
          const mdataItem = this.mdata.items && this.mdata.items.find(item => item.name === field.name)
          return extend(field, mdataItem, { title: field.title || (mdataItem && mdataItem.title) })
        })
      }
      if (cols.length === 0) {
        const defaultIncludeFields = ['name', 'title']
        this.mdata.items &&
          (cols = this.mdata.items.filter(item => {
            return defaultIncludeFields.indexOf(item.name) !== -1
          }))
      }
      cols = cols.map(item => {
        return extend(
          {
            label: item.title,
            field: item.name,
            align: 'left'
          },
          item
        )
      })
      this.itemMenuList.length && cols.push({ name: '__operator_group', label: '操作', align: 'left', operations: this.itemMenuList })
      return cols
    },
    pagination() {
      return {
        page: this.queryData.pageNo,
        rowsPerPage: this.queryData.pageSize,
        rowsNumber: this.queryData.totalNum
      }
    }
  },
  created: async function() {
    if (this.entity) {
      this.exportUrl = '/api' + (await this.genBaseUrl('/exportData'))
    }

    // 初始化 menu
    const itemMenuExt = (this.viewFields && this.viewFields.itemMenuExt) || ['edit', 'delete']
    for (const item of itemMenuExt) {
      if (this.itemMenuMap[item] && this.itemMenuMap[item].isEdit && !this.canEdit) {
        continue
      }
      if (typeof item === 'string') {
        this.itemMenuMap[item] && this.itemMenuList.push(this.itemMenuMap[item])
      } else if (this.itemMenuMap[item.name]) {
        this.itemMenuList.push(Object.assign({}, this.itemMenuMap[item.name], item))
      } else {
        this.itemMenuList.push(item)
      }
    }
    await this.queryMData(this.autoLoad)
  },
  watch: {
    async entity(old) {
      this.exportUrl = '/api' + (await this.genBaseUrl('/exportData'))
      await this.queryMData()
    },
    selectedMap(old) {
      this.selectedMapInner = old || {}
    },
    selectModel(old) {
      this.selectModelInner = old || 'more'
    },
    queryFilter(val) {
      this.query(val)
    },
    keyword() {
      this.filter.___keyword = this.keyword || ''
      this.query()
    },
    kybIsEdit(newValue) {
      this.isEdit = newValue
    },
    async kybMdata(newValue) {
      await this.queryMData()
    },
    async value(newValue) {
      this.queryData = newValue
      this.afterLoad()
    }
  },
  methods: {
    resetFilter() {
      this.filter = {}
      this.query()
    },
    getFieldTitle(f) {
      let field = f
      if (typeof f === 'object') {
        if (f.title) {
          return f.title
        }
        field = f.name
      }
      return (this.mdata.itemMap && this.mdata.itemMap[field] && this.mdata.itemMap[field].title) || field
    },
    getFieldValue(item, f, suffix) {
      const fieldObj = typeof f === 'object' ? f : this.mdata.itemMap[f] || { name: f }
      const field = fieldObj.name
      const { render, inputType } = fieldObj
      let value = item[field]
      // 带有路径的属性
      if (Object.keys(item).indexOf(field) === -1 && field.indexOf('.') !== -1) {
        const temp = field.split('.')
        if (item[temp[0]]) {
          value = this.getFieldValue(item[temp[0]], temp.slice(1).join('.'))
        }
      }
      if (render) {
        value = render(value, f, item)
      } else {
        if (value !== undefined) {
          if (inputType === 'dateTime') {
            value = date.formatDate(value, 'YYYY-MM-DD HH:mm:ss')
          } else if (inputType === 'date') {
            value = date.formatDate(value, 'YYYY-MM-DD')
          } else if (inputType === 'time') {
            value = date.formatDate(value, 'HH:mm:ss')
          }
          if (suffix && f.suffix) {
            value = value + f.suffix
          }
        }
      }

      return value
    },
    getField(f) {
      let field = typeof f === 'object' ? extend({}, f) : { name: f }
      if (this.mdata.itemMap && this.mdata.itemMap[field.name]) {
        extend(field, this.mdata.itemMap[field.name])
      }
      return field
    },
    async queryMData(autoLoad) {
      let keywordField = [...this.keywordFields]
      if (this.entity) {
        // 优先级最高，否则使用组件传入的mdata
        let response = await this.$axios.get(await this.genBaseUrl('/mdata'))
        // 初始化
        // this.tableShowField || (this.tableShowField = [])
        // let tableShowFieldIsEmpty = this.tableShowField.length === 0
        response.data.items.forEach(item => {
          item.$selected = true
          if (item.name === 'name' || item.name === 'title' || item.name === 'desc') {
            keywordField.push(item.name)
            // // 如果未指定，tableShowFiled
            // if (tableShowFieldIsEmpty) {
            //   this.tableShowField.push(item.name)
            // }
          }
        })
        this.headerFilter.selectAll = true
        this.mdata = response.data
      } else {
        this.mdata = extend({}, this.kybMdata)
      }

      this.mdata.items || (this.mdata.items = [])
      this.mdata.itemMap || (this.mdata.itemMap = {})
      this.mdata.items.forEach(item => {
        if (!item.inputType) {
          item.inputType = item.type
        }
        this.mdata.itemMap[item.name] = item
      })
      this.formatMdata && (await this.formatMdata(this.mdata))
      // console.log('--- this.mdata: ', this.mdata)
      if (keywordField.length && !this.queryFilter.___keyword_field) {
        this.filter.___keyword_field = keywordField.join(',')
      }
      if (autoLoad) {
        await this.query()
      }
    },
    onResizeHeader(size, item) {
      // console.log(size, item)
      item.$width = size.width
      this.$forceUpdate()
    },
    sortByHeader(item) {
      this.filter.pageNo = 1
      item.$orderByNum || (item.$orderByNum = 0)
      if (++item.$orderByNum % 3 === 0) {
        this.filter.orderBy = null
        this.filter.orderByAsc = null
      } else {
        this.filter.orderBy = item.name
        this.filter.orderByAsc = !this.filter.orderByAsc
      }
      this.query()
    },
    async query(queryFilter) {
      queryFilter || (queryFilter = {})
      Object.assign(this.filter, queryFilter)
      let url = this.queryUrl
      if (!url || !url.length) {
        if (this.entity) {
          url = await this.genBaseUrl('/query')
        } else {
          return
        }
      }
      url.indexOf('?') === -1 && (url += '?1=1')
      Object.keys(this.filter).filter(v => this.filter[v] !== undefined && this.filter[v] !== null).forEach(v => {
        url += `&${encodeURIComponent(v)}=${encodeURIComponent(this.filter[v])}`
      })
      let response = await this.$axios.get(url)
      this.queryData = response.data
      if (this.queryData.totalPage > 0 && this.filter.pageNo > this.queryData.totalPage && this.queryData.items.length === 0) {
        // 当前页大于总页数
        queryFilter.pageNo = 1
        return this.query(queryFilter)
      }
      return this.afterLoad()
    },
    afterLoad() {
      this.$set(this.queryData, 'selectAll', false)
      this.queryData.items.forEach(item => {
        this.$set(item, '$selected', this.selectedMapInner[item._id])
        this.$set(item, '$isEdit', false)
      })
      // 格式化数据
      this.formatData && this.formatData(this.queryData)
      let ju = 3
      let start = this.queryData.pageNo - ju
      start = start < 1 ? 1 : start
      let end = start + 2 * ju
      end = end > this.queryData.totalPage ? this.queryData.totalPage : end
      this.queryData.$pageNumList = []
      for (let i = start; i <= end; i++) {
        this.queryData.$pageNumList.push(i)
      }
      this.queryData.$pageStart = start
      this.queryData.$pageEnd = end

      // this.$q.showNotifi('查询成功')
      return this.queryData
    },
    quickInputClear() {
      _.map(this.newItem, (v, k) => {
        delete this.newItem[k]
      })
      _.map(this.filter, (v, k) => {
        if (k.startsWith('_')) {
          delete this.filter[k]
        }
      })

      if (!this.isEdit || !this.showAddRow) {
        this.query()
      }
    },
    quickInput(name) {
      if (!this.newItem[name] || !this.newItem[name].length) {
        delete this.filter['_' + name]
      } else {
        this.filter['_' + name] = '___like___' + this.newItem[name]
        this.filter.pageNo = 1
      }
      this.query()
    },
    addItem() {
      this.showForm(_.clone(this.detailInitData), true)
    },
    async showForm(item, isAdd, isEdit, options) {
      // 弹出表单方式
      this.editItem = item
      this.$$form || (this.$$form = Object.assign({}, this.form))

      isAdd === undefined && (isAdd = false)
      this.form.isAdd = isAdd
      isEdit === undefined && (isEdit = isAdd)
      if (isEdit !== undefined) {
        this.form.isEdit = isEdit
      }
      extend(this.form, options)
      this.showSaveFormWin = true
      // console.log('-------,this _uid: ', this._uid);
      // this.compCreated(this.editFormId, () => {
      //   // console.log('1params: ')
      //   item || (item = this.defaultItem)
      //   // alert('this.filter.pid:'+this.filter._pid);
      //   if (this.mdata.tableType === 'tree' && this.filter._pid) {
      //     item.pid = this.filter._pid
      //   }
      //   this.compSetData(this.editFormId, 'fdata', item)
      //   // console.log('2params: ')
      //   this.compSetData(this.editFormId, 'mdata', this.mdata)
      // })
    },
    async del(_id, index) {
      if (!this.isEdit) {
        this.$q.showNotifi('请打开编辑模式后执行删除操作！')
        return
      }
      this.$q
        .dialog({
          title: '请确认',
          message: '是否删除该条数据？',
          ok: {
            push: true
          },
          cancel: {
            color: 'grey-7'
          },
          persistent: true
        })
        .onOk(async () => {
          this.$emit('del-before', 'del', this.mdata, _id, index)
          if (this.entity) {
            await this.$axios.post(await this.genBaseUrl('/del'), { _id: _id })
            this.query()
          } else {
            this.queryData.items.splice(index, 1)
          }

          this.$emit('del-after', 'del', this.mdata, _id, index)
          this.$q.showNotifi('删除成功！')
        })
    },
    async delMore() {
      if (!this.isEdit) {
        return
      }
      this.queryData.selectCount || (this.queryData.selectCount = 0)
      if (this.queryData.selectCount === 0) {
        this.$q.showNotifi('请选择要删除的行！')
        return
      }
      this.$q
        .dialog({
          title: '请确认',
          message: this.queryData.selectCount + ' 条数据将被删除，请确认!',
          ok: {
            push: true
          },
          cancel: {
            color: 'grey-7'
          },
          persistent: true
        })
        .onOk(async () => {
          // 选择"OK"
          let ids = this.queryData.items
            .filter(item => {
              return item.$selected
            })
            .map(item => {
              return item._id
            })
            .join(',')
          this.$emit('del-before', 'delMore', this.mdata, ids)
          await this.$axios.post(await this.genBaseUrl('/delMore'), {
            ids: ids
          })
          this.query()
          this.$emit('del-after', 'delMore', this.mdata, ids)
          this.$q.showNotifi(`成功删除 ${this.queryData.selectCount} 条数据`)
        })
        .onCancel(() => {
          // 选择"Cancel"或作了关闭操作
        })
    },
    selectAll() {
      console.log(this.queryData.selectAll)
      if (this.queryData.selectAll == null) {
        this.queryData.selectAll = false
      }
      this.queryData.selectCount = !this.queryData.selectAll ? 0 : this.queryData.items.length
      let change = {}
      this.queryData.items.forEach(item => {
        item.$selected = this.queryData.selectAll
        this.selectedMapInner[item._id] = this.queryData.selectAll
        change[item._id] = item.$selected ? item : null
      })
      this.$emit('selected-change', change)
    },
    selectItem(item) {
      let selectMore = this.selectModelInner === 'more'
      this.selectedMapInner || (this.selectedMapInner = {})
      let keys = _.keys(this.selectedMapInner)
      // let change = {};
      if (!selectMore && keys.length > 0 && item.$selected) {
        // 单选
        let old = this.queryData.items.find(v => v._id === keys[0])
        if (old && old._id !== item._id) {
          old.$selected = false
        }
        this.selectedMapInner = {}
      }

      delete this.selectedMapInner[item._id]
      if (item.$selected) {
        this.selectedMapInner[item._id] = true
      }

      this.queryData.selectCount || (this.queryData.selectCount = 0)
      this.queryData.selectCount += item.$selected ? 1 : -1
      if (this.queryData.selectCount === this.queryData.items.length) {
        this.queryData.selectAll = true
      } else {
        if (this.queryData.selectCount > 0) {
          this.queryData.selectAll = null
        } else {
          this.queryData.selectAll = false
        }
      }
      this.$emit('selected-change', JSON.parse(JSON.stringify(this.selectedMapInner)))
    },
    selectCell(header, item) {
      this.selectedCell = { hid: header._id, _id: item._id }
    },
    selectAllHeader() {
      if (this.headerFilter.selectAll == null) {
        this.headerFilter.selectAll = false
      }
      this.mdata.items.forEach(item => {
        item.$selected = this.headerFilter.selectAll
      })
    },
    contentScroll(e) {
      this.topRightSLeft = this.centerLeft - e.target.scrollLeft
      this.downLeftSTop = this.centerTop - e.target.scrollTop
    },
    // 事件传递：
    saveBefore(type, mdata, data) {
      this.$emit('save-before', type, mdata, data)
    },
    saveAfter(type, mdata, data) {
      if (type === 'add') {
        this.queryData.items.push(data)
      }
      this.query()
      this.showSaveFormWin = false
      this.$emit(
        'save-after',
        type,
        mdata,
        data,
        this.queryData.items.findIndex(item => item === data)
      )
    },
    onFormItemChange(field, value, data) {
      this.$emit('form-item-change', field, value, data)
    },
    onFormItemBlur(field, value, data) {
      this.$emit('form-item-blur', field, value, data)
    },
    async saveCellToServer(header, data) {
      let reqData = {
        _id: data._id,
        versionNum: data.versionNum
      }
      reqData[header.name] = data[header.name]
      this.saveBefore('save', header, data)
      await this.$axios.post(await this.genBaseUrl('/save'), reqData)
      this.saveAfter('save', header, data)
    },
    async saveCell(header, item) {
      if (!this.isEdit) {
        this.$q.showNotifi('单击"锁"，开启编辑模式后修改！')
        return
      }
      if (header.type === 'boolean') {
        item[header.name] = !item[header.name]
        this.saveCellToServer(header, item)
      } else {
        this.editItem = item
        this.showSaveFormWin = true
      }
    },
    hideImportDataWin() {
      this.importDataWin = false
    }
  }
}

export default obj
</script>
<style lang="scss">
.kyb-table input {
  border-radius: 3px;
  border: 1px solid $grey-4;
  padding: 2px 4px;
}

.kyb-table-content {
  margin-bottom: 35px;
}

.table-call,
.kyb-table i.table-call {
  height: 36px;
  min-width: 36px;
  border-right: 1px solid $grey-5;
  border-bottom: 1px solid $grey-5;
  padding: 2px 5px;
  line-height: 32px;
  overflow: hidden;
}

.table-call.btn-con {
  width: 36px;
}

.table-call.right {
  border-right: 0px solid #fff !important;
}

.kyb-table .bg-light-0 {
  background-color: #eee;
}

.table-call:hover,
.kyb-table .item:hover,
.table-call.selected {
  background-color: #ddd;
  cursor: pointer;
}

.table-call.i.q-icon {
  width: 36px;
}

.list > .item {
  border-bottom: 1px solid $grey-4;
}

.list > .item.selected {
  background-color: #eee;
}

.table-row > .table-call {
  width: 100px;
}

.top_left {
  border-right: 1px solid $grey-4;
  box-shadow: 0 0 4px $grey-5;
}

.top_right {
  border-left: 1px solid $grey-4;
}

.down_left {
  bottom: 0px;
  left: 0px;
  border-right: 1px solid $grey-4;
  box-shadow: 0 0 4px $grey-5;
}

.down_right {
  right: 0;
  bottom: 0;
  border-top: 1px solid $grey-4;
  border-left: 1px solid $grey-4;
  overflow: scroll;
}

.table-row {
  flex-wrap: nowrap;
}

.kyb-table i.q-icon {
  font-size: 18px;
}

.kyb-table .header td {
  white-space: nowrap;
  font-weight: bolder;
}

.kyb-table .header i:hover,
.kyb-table .table-call i:hover {
  background-color: transparent;
}

.kyb-table > .kyb-table-header > .table-call {
  background-color: #eee;
}

.kyb-table > .kyb-table-content {
  flex: 1 1 auto;
}

.kyb-table > .kyb-table-footer {
  border-top: 1px solid $grey-3;
  display: flex;
  align-items: center;
  bottom: 0;
  right: 0;
  left: 0;
}

.kyb-table > .kyb-table-header > .table-call {
  text-align: center;
}

.table-call.int,
.table-call.long,
.table-call.float,
.table-call.double {
  text-align: right;
  color: blue;
}

.table-call.boolean {
  text-align: center;
}

.kyb-table td {
  max-width: 25%;
}

.kyb-table td {
  padding: 10px;
}
</style>
