<template>
  <vxe-grid 
    ref="tableRef" 
    v-bind="gridOptions" 
    :loading="props.loading" 
    :columns="props.columns" 
    :data="props.tableData"
    @cell-dblclick="cellDBLClickEvent" 
    :row-style="getRowStyle"
    @edit-actived="onEditActivated"
    @page-change="pageChange"
    >
    <template #toolbar_buttons>
      <vxe-button size="small" status="primary" icon="vxe-icon-add" @click="addRow()" v-if="hasAddRows">
        {{ addRowsText }}
      </vxe-button>
      <vxe-button size="small" status="danger" icon="vxe-icon-delete-fill" @click="delSelect" v-if="hasDelSelect">
        删除
      </vxe-button>
      <vxe-button size="small" status="success" icon="vxe-icon-save" @click="allSave" v-if="props.hasAllSave">
        保存
      </vxe-button>
    </template>
    <template #toolbar_buttons_new>
      <vxe-button size="small" status="primary" icon="vxe-icon-add" @click="addRow()" v-if="hasAddRows">
        {{ addRowsText }}
      </vxe-button>
      <vxe-button size="small" status="danger" icon="vxe-icon-delete-fill" @click="delSelect" v-if="hasDelSelect">
        删除
      </vxe-button>
    </template>
    <template #statusDef="{ row }">
      <vxe-switch v-model="row.status" size="mini"></vxe-switch>
    </template>
    <template #text="{ row, column }">
      <el-input
        @mousedown.stop 
        v-model="row[column?.field]" 
        placeholder="请输入内容"
        disabled
      />
    </template>
    <template #input="{ row, column }">
      <el-input 
        @mousedown.stop 
        v-model="row[column?.field]" 
        placeholder="请输入内容"
      />
    </template>
    <template #treeSelect="{ row, column }">
      <el-tree-select 
        @mousedown.stop 
        v-model="row[column?.field]" 
        :data="typeof column.slots.data === 'function' ? column.slots.data(row,column) : column.slots.data"
        :props="column.slots.props"
        check-strictly 
        :default-expand-all="true" 
        :value-key="column.slots.key" 
        :size="column.slots.size" 
        @change="($event) => { column.slots.change($event, row, column)}" 
      />
    </template>
    <template #select="{ row, column }">
      <el-select @mousedown.stop v-model="row[column?.field]" @change="column?.slots.change($event,row,column)" :disabled="column?.slots.disabled" :filterable="column?.slots.filterable" @visible-change="column?.slots.visibleChange($event,row,column)">
        <el-option v-for="dict in column?.slots.options" :key="dict[column?.slots.key]" :label="dict[column?.slots.label]"
                :value="dict[column?.slots.value]" />
      </el-select>
    </template>
    <template #operate="{$table, row, column }">
      <template v-if="hasEditRows(row)">
        <vxe-button size="small" type="text" content="取消" icon="vxe-icon-close" @click="cancelRowClick"></vxe-button>
        <vxe-button size="small" type="text" status="primary" content="保存" icon="vxe-icon-check"
          @click="saveRowClick(row)"></vxe-button>
      </template>
      <template v-else>
        <vxe-button v-if="getButtonShow($table,row,'newButton')" size="small" type="text" :content="getButtonInfo($table,row,'name','newButton')" icon="vxe-icon-edit" @click="getButtonInfo($table,row,'btn','newButton')"></vxe-button>
        <vxe-button v-if="getButtonShow($table,row,'newButtonTwo')" size="small" type="text" :content="getButtonInfo($table,row,'name','newButtonTwo')" icon="vxe-icon-edit" @click="getButtonInfo($table,row,'btn','newButtonTwo')"></vxe-button>
        <vxe-button size="small" type="text" content="编辑" icon="vxe-icon-edit" v-if="hasEditRow"
          @click="editRowClick(row)"></vxe-button>
      </template>
      <vxe-button size="small" type="text" status="danger" content="删除" icon="vxe-icon-delete" v-if="hasdelRow"
        @click="delRowClick(row)"></vxe-button>
    </template>
    <template #operateNew="{$table, row, column }">
      <template v-if="hasEditRows(row)">
        <vxe-button size="small" type="text" content="取消" icon="vxe-icon-close" @click="cancelRowClick"></vxe-button>
        <vxe-button size="small" type="text" status="primary" content="保存" icon="vxe-icon-check"
          @click="saveRowClick(row)"></vxe-button>
      </template>
      <template v-else>
        <vxe-button v-if="getButtonShow($table,row,'newButton')" size="small" type="text" :content="getButtonInfo($table,row,'name','newButton')" icon="vxe-icon-edit" @click="getButtonInfo($table,row,'btn','newButton')"></vxe-button>
        <vxe-button v-if="getButtonShow($table,row,'newButtonTwo')" size="small" type="text" :content="getButtonInfo($table,row,'name','newButtonTwo')" icon="vxe-icon-edit" @click="getButtonInfo($table,row,'btn','newButtonTwo')"></vxe-button>
        <vxe-button size="small" type="text" content="编辑" icon="vxe-icon-edit" v-if="hasEditRow"
          @click="editRowClick(row)"></vxe-button>
      </template>
      <vxe-button size="small" type="text" status="danger" content="删除" icon="vxe-icon-delete" v-if="hasdelRow"
        @click="delRowClick(row)"></vxe-button>
    </template>
  </vxe-grid>
</template>

<script setup>
import { reactive,defineExpose } from "vue";
import { VXETable } from "vxe-table";
const { proxy } = getCurrentInstance();
const tableRef = ref();
const tableHeight = ref('0px');
const rowHeight = ref(44);
const headerHeight = ref(66);
const emit = defineEmits([
  "insertRecords",
  "updateRecords",
  "delSelectData",
  "allSaveRowData",
  "saveRowData",
  "delRowData",
  "btnClick",
  "cellDBLClick",
  "pageChange",
  "beforeEditRowsCallBack",
  "validateFormMethod",
  "beforeAddRowsCallBack",
  "addRowsCallBack",
]);

const props = defineProps({
  config: {
    //表格配置项
    type: Object,
    default: {
      //表格配置项
      id: "table", //唯一标识
      height: "auto", //表格的高度；支持铺满父容器或者固定高度
      align: "center", //所有的列对齐方式
      border: "none", //是否带有边框:false|default 默认显示边框,true|full 显示完整边框,outer 显示外边框,inner 显示内边框,none
      round: true, //是否为圆角边框
      stripe: true, //是否带有斑马纹
      size: "medium", //表格的尺寸:medium, small, mini
      // loading: false, //表格是否显示加载中
      showHeader: true, //是否显示表头
      columnConfig: {
        //列配置信息
        isCurrent: false, //当鼠标点击列头时，是否要高亮当前列
        isHover: true, //当鼠标移到列头时，是否要高亮当前头
      },
      rowConfig: {
        //行配置信息
        keyField: "id", //自定义行数据唯一主键的字段名
        isCurrent: false, //当鼠标点击行时，是否要高亮当前行
        isHover: true, //当鼠标移到行时，是否要高亮当前行
      },
      editConfig: {
        //可编辑配置项
        trigger: "dblclick", //触发方式click（点击触发编辑）,dblclick（双击触发编辑）
        mode: "row", //编辑模式cell（单元格编辑模式）,row（行编辑模式）
      },
      pagerConfig: {
        //分页配置项
        enabled: true, //是否启用
        currentPage: 1, //当前页
        pageSize: 10, //每页大小
        total: 0, //总条数
        autoHidden: true, //当只有一页时自动隐藏
        pageSizes: [10, 15, 20, 50, 100], //每页大小选项列表
      },
      toolbarConfig: {
        //工具栏配置
        refresh: true, // 显示刷新按钮
        import: false, // 显示导入按钮
        export: false, // 显示导出按钮
        zoom: true, // 显示全屏按钮
        custom: true, // 显示自定义列按钮
      },
    },
  },
  colField: {
    //新增时默认可编辑字段
    type: String,
    default: "",
  },
  additional: {
    //新增时增加默认显示字段
    type: Object,
    default: {},
  },
  columns: {
    //表格表头数据
    type: Array,
    default: [],
  },
  tableData: {
    //表格数据
    type: Array,
    default: [],
  },
  loading: {
    type: Boolean,
    default: false,
  },
  addRowsText: {
    //新增按钮文字
    type: String,
    default: "新增",
  },
  addRowsType: {
    //新增按钮类型，1新增功能，2纯按钮用于其他操作
    type: Number,
    default: 1,
  },
  hasAddRows: {
    //是否显示新增按钮
    type: Boolean,
    default: true,
  },
  hasDelSelect: {
    //是否显示删除按钮
    type: Boolean,
    default: true,
  },
  hasAllSave: {
    //是否显示保存
    type: Boolean,
    default: true,
  },
  hasEditRow: {
    //是否显示操作编辑按钮
    type: Boolean,
    default: true,
  },
  hasdelRow: {
    //是否显示操作删除按钮
    type: Boolean,
    default: true,
  },
  pagination: {
    //分页
    type: Object,
    default: {
      total: 0,
      currentPage: 1,
      pageSize: 10,
    },
  },
});
const { config, colField, addRowsType, hasAddRows, hasDelSelect } = props;

const gridOptions = reactive({
  id: config.id, //唯一标识
  height: tableHeight, //表格的高度；支持铺满父容器或者固定高度
  maxHeight: config.maxHeight,
  minHeight: 200, //最小高度
  autoResize: true, //自动监听父元素的变化去重新计算表格
  align: config.align, //所有的列对齐方式
  border: config.border, //是否带有边框
  round: config.round, //是否为圆角边框
  stripe: config.stripe, //是否带有斑马纹
  size: config.size, //表格的尺寸:medium, small, mini
  // loading: config.loading, //表格是否显示加载中
  showHeader: config.showHeader, //是否显示表头
  showOverflow: true, //设置所有内容过长时显示为省略号
  headerRowClassName: "headerRowClass", //表头的行附加 className
  headerCellClassName: "headerCellClass", //头的单元格附加 className
  rowClassName: "rowClass", //行附加 className
  cellClassName: "cellClass", //单元格附加 className
  keepSource: true, //保持原始值的状态，被某些功能所依赖，比如编辑状态、还原数据等
  columnConfig: {
    //列配置信息
    isCurrent: config.columnConfig.isCurrent, //当鼠标点击列头时，是否要高亮当前列
    isHover: config.columnConfig.isHover, //当鼠标移到列头时，是否要高亮当前头
    resizable: true, //每一列是否启用列宽调整
  },
  rowConfig: {
    //行配置信息
    keyField: config.rowConfig.keyField, //自定义行数据唯一主键的字段名
    isCurrent: config.rowConfig.isCurrent, //当鼠标点击行时，是否要高亮当前行
    isHover: config.rowConfig.isHover, //当鼠标移到行时，是否要高亮当前行
  },
  sortConfig: {
    //排序配置项
    trigger: "cell", //触发方式
    multiple: false, //是否启用多列组合筛选
    remote: false, //所有列是否使用服务端排序，如果设置为 true 则不会对数据进行处理
  },
  filterConfig: {
    //筛选配置项
    remote: true, //所有列是否使用服务端筛选，如果设置为 true 则不会对数据进行处理
  },
  editConfig: {
    //可编辑配置项
    trigger: config.editConfig.trigger, //触发方式click（点击触发编辑）,dblclick（双击触发编辑）
    mode: config.editConfig.mode, //编辑模式cell（单元格编辑模式）,row（行编辑模式）
    showStatus: true, //只对 keep-source 开启有效，是否显示单元格新增与修改状态
    beforeEditMethod(param) {
      let shouldContinue;
      emit("beforeEditRowsCallBack", param);
      emit("validateFormMethod", param, val => {
        shouldContinue = val
      });
      if (shouldContinue || shouldContinue === undefined) {
        return true;
      } else {
        return false;
      }
    }
  },
  pagerConfig: {
    //分页配置项
    enabled: config.pagerConfig.enabled, //是否启用
    currentPage: config.pagerConfig.currentPage, //当前页
    pageSize: config.pagerConfig.pageSize, //每页大小
    total: config.pagerConfig.total, //总条数
    autoHidden: config.pagerConfig.autoHidden, //当只有一页时自动隐藏
    pageSizes: config.pagerConfig.pageSizes, //每页大小选项列表
  },
  toolbarConfig: {
    //工具栏配置
    slots: {
      //插槽
      buttons: "toolbar_buttons",
    },
    refresh: config.toolbarConfig.refresh, // 显示刷新按钮
    import: config.toolbarConfig.import, // 显示导入按钮
    export: config.toolbarConfig.export, // 显示导出按钮
    // print: true, // 显示打印按钮
    zoom: config.toolbarConfig.zoom, // 显示全屏按钮
    custom: config.toolbarConfig.custom, // 显示自定义列按钮
  },
  importConfig: {
    //导入配置项
    remote: false, //是否服务端导入
    types: ["csv", "html", "xml", "txt"],
    modes: ["covering", "insert"],
  },
  exportConfig: {
    //导出配置项
    remote: false, //是否服务端导出
    types: ["csv", "html", "xml", "txt"], //可选文件类型列表
    modes: ["current", "selected", "all"], //输出数据的方式列表
  },
  editRules: config.editRules, //校验规则配置项
  // columns: config.columns,
  // data: config.data,
});

const addRow = async (row) => {
  const $table = tableRef.value;
  //新增按钮
  if (addRowsType === 1) {
    //新增功能
    if ($table) {
      let shouldContinue = true;
      emit("beforeAddRowsCallBack", $table, val => { shouldContinue = val });
      if (shouldContinue || shouldContinue === undefined) {
        const record = props.additional;
        const { row: newRow } = await $table.insertAt(record, row);
        await $table.setEditCell(newRow, colField);
        emit("addRowsCallBack", newRow);
        calculateTableHeight(null);
      } else {
        // 不继续执行下面的代码
        return;
      }
      
    }
  } else if (addRowsType === 2) {
    //新增功能
    if ($table) {
      let shouldContinue = true;

      console.log("shouldContinue");
      emit("beforeAddRowsCallBack", $table, val => { shouldContinue = val });
      if (shouldContinue || shouldContinue === undefined) {debugger
        //纯按钮功能
        emit("btnClick", "")
      }
    }
  }
};

const delSelect = async () => {
  //多选删除
  const $table = tableRef.value;
  const selectRecords = $table.getCheckboxRecords();
  if ($table && selectRecords.length != 0) {
    const type = await VXETable.modal.confirm("您确定要删除该数据?");
    if (type === "confirm") {
      emit("delSelectData", selectRecords);
      $table.removeCheckboxRow();
    }
  } else {
    VXETable.modal.message({
      content: "请选择要删除的数据！",
      status: "warning",
    });
  }
};
const allSave = async () => {
  //多行编辑保存
  const $table = tableRef.value;
  if ($table) {
    const $grid = tableRef.value;
    const errMap = await $grid.validate(true);
    if (errMap) {
      VXETable.modal.message({ status: "error", content: "请填写相关内容！" });
    } else {
      // const updateRecords = $table.getUpdateRecords();
      const { insertRecords, removeRecords, updateRecords } =
        $grid.getRecordset();
      if (insertRecords.length != 0) {
        console.log(insertRecords);
        //新增
        emit("insertRecords", insertRecords);
      } else if (updateRecords.length != 0) {
        //修改
        emit("updateRecords", updateRecords);
      }
     
    }
  }
};
const hasEditRows = (row) => {
  //显示编辑或保存按钮
  const $grid = tableRef.value;
  if ($grid) {
    return $grid.isEditByRow(row);
  }
  return false;
};
const editRowClick = async (row) => {
  //点击编辑
  const $grid = tableRef.value;
  if ($grid) {
    const payload = {
      grid: $grid,
      row: row
    };
    $grid.setEditRow(row);
  }
};
const cancelRowClick = () => {
  //点击取消
  const $grid = tableRef.value;
  if ($grid) {
    $grid.clearEdit();
  }
};
const saveRowClick = async (row) => {
  //编辑保存
  const $grid = tableRef.value;
  if ($grid) {
    const errMap = await $grid.validate(true);
    if (errMap) {
      VXETable.modal.message({ status: "error", content: "请填写相关内容！" });
    } else {
      await $grid.clearEdit();
      const { insertRecords, removeRecords, updateRecords } =
        $grid.getRecordset();
      if (insertRecords.length != 0) {
        //新增
        emit("insertRecords", insertRecords)
      } else if (updateRecords.length != 0) {
        //修改
        emit("updateRecords", updateRecords)
      }
    }
  }
};
const saveRowClickNew = async (row) => {
  //编辑保存
  const $grid = tableRef.value;
  if ($grid) {
    const errMap = await $grid.validate(true);
    if (errMap) {
      VXETable.modal.message({ status: "error", content: "请填写相关内容！" });
    } else {
      await $grid.clearEdit();
    }
  }
};
const delRowClick = async (row) => {
  //单行删除
  const type = await VXETable.modal.confirm("您确定要删除该数据?");
  const $grid = tableRef.value;
  if ($grid) {
    if (type === "confirm") {
      emit("delRowData", row);
      await $grid.remove(row);
    }
  }
};
const cellDBLClickEvent = ({ row, column, $event }) => {
  //双击单元格事件
  emit("cellDBLClick", row, column, $event);
};
const pageChange = ({ currentPage, pageSize }) => {
  //分页
  emit("pageChange", currentPage, pageSize);
};

// 动态计算函数
function calculateTableHeight(rowHeightNew) {
  const $table = tableRef.value
  let newRowNum = 0;
  let pageHeight = 0;
  if (rowHeightNew) {
    rowHeight.value = rowHeightNew;
  }
  if ($table) {
    const insertRecords = $table.getInsertRecords()
    newRowNum = insertRecords.length;
  }
  if (props.pagination.total > 10) {
    pageHeight = 44;
  }
  const rowCount = props.tableData?.length
  headerHeight.value = tableRef.value.$el.querySelector('.vxe-header--row')?.offsetHeight
  tableHeight.value = (newRowNum + rowCount) * (rowHeight.value + 1.8) + (48.8 + pageHeight + 5) + headerHeight.value + 'px'
}

//监控config的变化，目前重新计算了表格高度
watch(config, (newConfig) => {
  console.log('newConfig');
  console.log(newConfig);
  // 监听 config 变化的处理逻辑
  gridOptions.minHeight = newConfig.minHeight;
  gridOptions.maxHeight = newConfig.maxHeight;
  rowHeight.value = newConfig.rowHeight;
  gridOptions.pagerConfig.currentPage = newConfig.pagerConfig.currentPage;
  gridOptions.pagerConfig.pageSize = newConfig.pagerConfig.pageSize;
  gridOptions.pagerConfig.total = newConfig.pagerConfig.total;

}, { deep: true });

//自定义表格高度根据行数行高自动调节，监控props.tableData的变化
watch(() => props.tableData, (newTableData) => {
  calculateTableHeight(config.rowHeight);
}, { deep: true });

//动态行样式
//1、获取响应式变量高度，其中rowHeight=ref(config.rowHeight);
function getRowStyle() {
  return { height: rowHeight.value + 'px' };
}

function onEditActivated(params) {
  const { row, $table } = params;
  // 遍历每一列
  $table.getColumns().forEach(column => {
    // 判断是否包含某属性 
    if (column && column?.slots!==undefined) {
      if(column.slots.hasOwnProperty('editActiveMethod')){
        //当包含编辑激活回调函数时则调用该函数
        column.slots.editActiveMethod(row,column);
      }
    }
  });
}

function getButtonInfo($table, row, operate, buttonDom) {
  const columns = $table.getColumns();
  for (let i = 0; i < columns.length; i++) {
    let column = columns[i];
    if(column?.title !== '操作'){
      continue;
    }
    if (column && column?.slots!==undefined) {
      if(column.slots.hasOwnProperty(buttonDom)){
        if (column.slots[buttonDom]) {
          const template = column.slots[buttonDom];
          if(operate === 'name'){
            if(template.hasOwnProperty('name')){
              return template.name;
            }
          }else if(operate === 'btn'){
            if(template.hasOwnProperty('click')){
              return template.click(row);
            }
          }
        }
      }
    } 
  }
  return '';
}

function getButtonShow($table, row, buttonDom) {
  const columns = $table.getColumns();
  for (let i = 0; i < columns.length; i++) {
    let column = columns[i];
    if(column?.title !== '操作'){
      continue;
    }
    if (column && column?.slots!==undefined) {
      if(column.slots.hasOwnProperty(buttonDom)){
        return true;
      }
    } 
  }
  return false;
}

async function addRows(num) {
  const $table = tableRef.value;
  const record = props.additional;
  let records = new Array(num).fill(record);
  emit("addRowsCallBack",records, results => records = results);
  await $table.insertAt(records, null);
  calculateTableHeight();
}


//自定义表格高度根据行数行高自动调节
// watch(() => tableRef?.value?.getInsertRecords(), (newTableData) => {
//   calculateTableHeight();
// }, { deep: true });

function getInsertRows() {
  const $table = tableRef.value;
  return $table.getInsertRecords();
}

const allSubmit = async (callback) => {
  //多行编辑保存
  const $table = tableRef.value;
  if ($table) {
    const $grid = tableRef.value;
    const errMap = await $grid.validate(true);
    if (errMap) {
      VXETable.modal.message({ status: "error", content: "请填写相关内容！" });
    } else {
      // const updateRecords = $table.getUpdateRecords();
      const { insertRecords, removeRecords, updateRecords } =
        $grid.getRecordset();
      if (insertRecords.length != 0) {
        console.log(insertRecords);
        //新增
        emit("insertRecords", insertRecords);
      } else if (updateRecords.length != 0) {
        //修改
        emit("updateRecords", updateRecords);
      } 
      await callback();
    }
    
  }
};

// // 将方法暴露出去
defineExpose({ addRows,getInsertRows,allSave,allSubmit });

</script>

<style lang="scss"></style>
