<template>
  <div class="page-body">
    <a-row type="flex">
      <a-col :flex="$mk.config.ui.searchFlex">
        <!-- 搜索区 -->
        <vxe-form :data="options.searchFormData" :items="options.searchFormItems" titleColon @submit="onSearch2()">
          <template #date="{}">
            <a-form-item label="创建时间" :style="{ display: 'inline-block', width: 120 }">
            </a-form-item>
            <a-form-item :style="{ display: 'inline-block', width: 'calc(100% - 120px )' }">
              <a-range-picker @change="onDateChange" />
            </a-form-item>
          </template>
        </vxe-form>
      </a-col>
      <a-col :flex="$mk.config.ui.toolbarFlex">
        <!-- 工具条 -->
        <mk-toolbar @toolbarClick="toolbarClick"></mk-toolbar>
      </a-col>
    </a-row>

    <vxe-toolbar ref="xToolbar" custom>
      <template #buttons>
        <a-button type="primary" icon="delete" @click="pageDelete()">批量删除</a-button>
        <a-button type="primary" style="margin-left: 5px;" icon="export" v-if="options.enabledExport"
          @click="pageExport()">导出</a-button>
        <a-button type="primary" style="margin-left: 5px;" icon="import" v-if="options.enabledImport"
          @click="pageImport()">导入</a-button>
        <a-button type="default" style="margin-left: 5px;" v-if="options.enabledImportTemplate"
          @click="pageImportTemplate()">下载导入模板</a-button>
      </template>
    </vxe-toolbar>
    <!-- 表格区 -->
    <div class="gridPanel">
      <vxe-grid ref='xGrid' v-bind="options.gridOptions">
        <template #op="{ row }">
          <div class="oplinks">
            <a @click.stop="pageEdit(row)" title="编辑"><a-icon type="edit" /></a>
            <a @click.stop="pageDelete(row)" title="删除"><a-icon type="delete" /></a>
          </div>
        </template>

        <template #column1="{ row }">
          <slot name="column1" :row="row"></slot>
        </template>

        <template #column2="{ row }">
          <slot name="column2" :row="row"></slot>
        </template>
        <template #column3="{ row }">
          <slot name="column3" :row="row"></slot>
        </template>
        <template #column4="{ row }">
          <slot name="column4" :row="row"></slot>
        </template>
        <template #column5="{ row }">
          <slot name="column5" :row="row"></slot>
        </template>
      </vxe-grid>
    </div>


    <vxe-modal v-model="showSheetNameSelector" width="500" height="400" title="选择表名">
      <template #default>
        <div>
          <vxe-select v-model="excelSheetName" placeholder="选择表名" style="width:100%">
            <vxe-option v-for="n in excelSheetNames" :key="n" :value="n" :label="n"></vxe-option>
          </vxe-select>
        </div>
        <div style="margin-top:10px;">
          <vxe-button status="primary" content="确定" @click="importOk"></vxe-button>
        </div>
      </template>
    </vxe-modal>
  </div>
</template>

<script>

import FileSaver from 'file-saver'
import * as XLSX from 'xlsx'
import { read, utils } from "xlsx"; // 注意处理方法引入方式


export default {
  name: 'BasicPageList',
  props: {
    options: {
      type: Object
    }
  },
  data() {

    return {
      showSheetNameSelector: false, excelSheetName: '', excelSheetNames: [],
 
      bindSearchData: null
    };

  },

  // 计算属性
  computed: {
  },

  // 创建完成
  created() {

    let _this = this;

    this.$nextTick(() => { // 在下次 DOM 更新循环结束之后执行延迟回调
      // 将表格和工具栏进行关联
      this.$refs.xGrid.connect(this.$refs.xToolbar) // 将表格和工具栏进行关联
    });


    this.options.gridOptions.proxyConfig = { // 配置代理
      sort: true, // 启用排序代理，当点击排序时会自动触发 query 行为
      filter: true, // 启用筛选代理，当点击筛选时会自动触发 query 行为
      props: {
        result: this.options.listFieldName, // 配置响应结果列表字段
        total: 'total' // 配置响应结果总页数字段
      },
      // 接收Promise
      ajax: {
        // 当点击工具栏查询按钮或者手动提交指令 query或reload 时会被触发
        query: (options) => { // options 为当前表格的配置项
          const { page, sorts } = options; // 获取当前页码、每页条数、排序信息
          var params = {}; // 定义请求参数
          params.page = page.currentPage; // 当前页码
          params.limit = page.pageSize; // 每页条数
          params.order_bys = []; // 排序信息
          params.search_rules = _this.getSearchParms(); // 搜索信息
          if (sorts) { // 如果有排序信息
            sorts.forEach((v) => { // 遍历排序信息
              params.order_bys.push({ // 添加排序信息
                column: v.property, // 字段名
                order: v.order // 排序方式
              })
            });
          }
          return _this.loadData({ params }); // 返回请求结果
        }
      }
    };

  },
  // 挂载完成
  onLoad() {




  },
  // 动作
  methods: {

    pageExport() {
      let jsonRows = [];
      let headerCells = [];

      for (let i = 0; i < this.options.exportColumns.length; i++) {
        let item = this.options.exportColumns[i];
        headerCells.push(item.title);
      }




      let details = JSON.parse(JSON.stringify(this.$refs.xGrid.getTableData().fullData));


      details.forEach(row => {
        let jsonRow = {
        };
        for (let i = 0; i < this.options.exportColumns.length; i++) {
          let item = this.options.exportColumns[i];
          var v = "";
          if (item.valueGetter) {
            v = item.valueGetter({ row: row, column: item });
          }
          else if (item.dataField) {
            v = row[item.dataField];
            if (item.textField && v) {
              v = v[item.textField]
            }
          } else {
            v = row[item.field] || '';
          }

          jsonRow[item.title] = v;
        }
        jsonRows.push(jsonRow);
      });
      var worksheet = XLSX.utils.json_to_sheet(jsonRows, { header: headerCells, skipHeader: false });

      const workbook = XLSX.utils.book_new();
      XLSX.utils.book_append_sheet(workbook, worksheet, "Sheet1");

      /* get binary string as output */
      var wbout = XLSX.write(workbook, { bookType: 'xlsx', bookSST: true, type: 'array' })
      try {
        FileSaver.saveAs(new Blob([wbout], { type: 'application/octet-stream' }), (this.options.exportFileTitle || '导出数据') + '.xlsx')
      } catch (e) {
        if (typeof console !== 'undefined') {
          console.log(e, wbout)
        }
      }
    },
    pageImportTemplate() {
      let jsonRows = [];
      let headerCells = [];

      for (let i = 0; i < this.options.exportColumns.length; i++) {
        let item = this.options.exportColumns[i];
        headerCells.push(item.title);
      }
      var worksheet = XLSX.utils.json_to_sheet(jsonRows, { header: headerCells, skipHeader: false });

      const workbook = XLSX.utils.book_new();
      XLSX.utils.book_append_sheet(workbook, worksheet, "Sheet1");
      /* get binary string as output */
      var wbout = XLSX.write(workbook, { bookType: 'xlsx', bookSST: true, type: 'array' })
      try {
        FileSaver.saveAs(new Blob([wbout], { type: 'application/octet-stream' }), '导入模板.xlsx')
      } catch (e) {
        if (typeof console !== 'undefined') {
          console.log(e, wbout)
        }
      }
    },
    pageImport() {
      let fileForm = document.createElement('form');
      let fileInput = document.createElement('input');
      fileForm.className = 'vxe-table--file-form';
      fileInput.name = 'file';
      fileInput.type = 'file';
      fileForm.appendChild(fileInput);
      document.body.appendChild(fileForm);

      fileInput.multiple = false;
      fileInput.accept = '';

      fileInput.onchange = (evnt) => {
        var files = evnt.target.files;
        var file = files[0];
        this.readExcel(file)
      };

      fileForm.reset();
      fileInput.click();
    },
    readExcel(file) {
      const fileReader = new FileReader();
      this.$mk.loading("读取中...");
      fileReader.onload = ev => {
        try {
          const data = ev.target.result;
          const workbook = read(data, { type: "binary" });
          this.workbook = workbook;
          this.excelSheetNames = workbook.SheetNames;
          this.showSheetNameSelector = true;
          this.$mk.hideLoading();



        } catch (e) {
          console.log("error:" + e);
          return false;
        }
      }
      fileReader.readAsBinaryString(file);
    },

    importOk() {
      this.showSheetNameSelector = false;

      const { workbook, excelSheetName } = this;
      if (!excelSheetName) {
        return;
      }
      let tableData = utils.sheet_to_json(workbook.Sheets[excelSheetName]);

      this.$emit("importData", { data: tableData });

    },
    // 修改日期
    onDateChange(date) { // 日期选择器事件
      if (date && date.length) { // 如果有值 
        date[0]._d.setHours(0, 0, 0, 0);
        date[1]._d.setHours(23, 59, 59, 59);
        this.start_time = parseInt(date[0]._d.getTime() / 1000); // 将日期转换为时间戳
        this.end_time = parseInt(date[1]._d.getTime() / 1000); // 将日期转换为时间戳
      } else { // 如果没有值
        this.start_time = 0; // 将日期转换为时间戳
        this.end_time = 0; // 将日期转换为时间戳
      }
    },
    // 获取搜索参数
    getSearchParms() { // 获取搜索参数
      var rules = []; // 定义搜索参数
      let findMode = k => { // 查找搜索模式
        for (let i in this.options.searchRules) { // 遍历搜索规则
          if (this.options.searchRules[i].key == k) return this.options.searchRules[i].mode; // 如果找到了就返回搜索模式
        }
        return "="; // 如果没有找到就返回等于
      };

      for (let key in this.options.searchFormData) { // 遍历搜索表单数据
        let value = this.options.searchFormData[key]; // 获取值
        if (value) { // 如果有值
          let mode = findMode(key); // 获取搜索模式
          if (mode == "like") { // 如果是模糊搜索
            value = "%" + value + "%"; // 如果是模糊搜索就在两边加上%
          }
          if (typeof (value) == "object" && value.id) {
            value = value.id;
          }
          rules.push({ // 添加搜索参数
            column: key, // 字段名
            mode: mode, // 搜索模式
            value: value // 值
          });
        }
      }
      if (this.bindSearchData) {
        for (let key in this.bindSearchData) { // 遍历搜索表单数据
          let value = this.bindSearchData[key]; // 获取值
          if (value) { // 如果有值
            let mode = findMode(key); // 获取搜索模式
            if (mode == "like") { // 如果是模糊搜索
              value = "%" + value + "%"; // 如果是模糊搜索就在两边加上%
            }
            rules.push({ // 添加搜索参数
              column: key, // 字段名
              mode: mode, // 搜索模式
              value: value // 值
            });
          }
        }

      }


      return rules; // 返回搜索参数
    },
    // 获取选中行
    getSelectdRow() { // 获取选中行
      let row = this.$refs.xGrid.getCurrentRecord(); // 获取当前行
      if (!row) { // 如果没有选中行
        let rows = this.$refs.xGrid.getCheckboxRecords(); // 获取选中行
        if (rows && rows.length) { row = rows[0]; } // 如果有选中行就取第一行
      }
      return row; // 返回选中行
    },
    // 加载数据
    loadData({ params }) {
      params.start_time = this.start_time; // 开始时间
      params.end_time = this.end_time; // 结束时间
      return this.$mk.getPagedData({
        url: this.options.actions.getList,
        data: params
      });
    },

    // 工具栏点击事件 add / log / setting
    toolbarClick(e) {
      if (e.name == "add") { // 如果是添加

        if (this.options.editPage) {
          this.$mk.dialog.open({
            page: this.options.editPage,
            title: this.options.editPageTitle,
            pageOptions: {
            },
            width: this.$mk.getWindowSize().width * 0.9,
            height: this.$mk.getWindowSize().height * 0.9,
            dataId: 0,
            callback: ({ success }) => {
              if (success) {
                this.$refs.xGrid.commitProxy('query')
              }
            }
          });
        } else {
          this.$openPage(this.options.addPageUrl); // 打开页面  
        }



      }
      else if(e.name == "setting"){
        this.openSettingPage();

      }
    },
    openSettingPage() { 
      this.$mk.dialog.open({
        page: () => import("./setting"),
        title: "配置",
        pageOptions: this.options.settings,
        width: 800,
        height: 600,
        dataId: 0,
        callback: ({ success }) => {
          if (success) {
            this.$refs.gridRouter.commitProxy('query')
          }
        }
      });
    },

    getPageList() {

      let target = [];

      let find = (component) => {

        if (component && component.pageList) {
          target = component.pageList;
        }
        if (component.$parent) {
          find(component.$parent)
        }
      }

      find(this.$parent);


      return target;
    },
    isEditPageOpen() {
      let pageList = this.getPageList();
      if (pageList.filter(a => a.keyPath && a.keyPath.indexOf(this.options.editPageUrl) == 0).length) {
        return true;
      }
      return false;
    },

    getTabsViewPageComponent() {

      let target = null;

      let find = (component) => {

        if (component && component.pageList) {
          target = component;
        }
        if (component.$parent) {
          find(component.$parent)
        }
      }

      find(this.$parent);


      return target;
    },
    //找到定义了beforeTabClose方法 的页面组件
    findEditPageComponent(key) {
      if (!key) {
        return null;
      }
      let target = null;


      let find = (children) => {
        children.forEach(item => {
          if (item.beforeTabClose && item.pageKeys && item.pageKeys.filter(a => key.indexOf(a) == 0).length) {
            target = item;
            return;
          }
          if (item.$children && item.$children.length) {
            find(item.$children)
          }
        })
      }
      let tabsview = this.getTabsViewPageComponent();
      if (tabsview == null) {
        return null;
      }
      find(tabsview.$children);


      return target;
    },
    // 编辑
    pageEdit(row) {
      if (!row) { // 如果没有选中行
        this.$mk.msg("请选择行"); // 提示
        return; // 返回
      }
      if (this.isEditPageOpen()) {
        let editPage = this.findEditPageComponent(this.options.editPageUrl);
        if (editPage != null) {
          editPage.beforeTabClose().then(() => {
            this.$closePage(this.options.editPageUrl);
            this.showPageEdit(row[this.options.keyName]); // 打开页面
          });
        } else {
          this.showPageEdit(row[this.options.keyName]); // 打开页面
        }

      } else {
        this.showPageEdit(row[this.options.keyName]); // 打开页面
      }



    },


    showPageEdit(dataId) {

      if (this.options.editPage) {
        this.$mk.dialog.open({
          page: this.options.editPage,
          title: this.options.editPageTitle,
          pageOptions: {
          },
          width: this.$mk.getWindowSize().width * 0.9,
          height: this.$mk.getWindowSize().height * 0.9,
          dataId: dataId,
          callback: ({ success }) => {
            if (success) {
              this.$refs.xGrid.commitProxy('query')
            }
          }
        });
      } else {
        this.$openPage(this.options.editPageUrl + dataId);
      }

    },


    // 删除
    pageDelete(row) {
      let rows = row ? [row] : this.$refs.xGrid.getCheckboxRecords(); // 获取选中行
      let ids = []; // 定义id数组
      rows.forEach((row) => { // 遍历选中行
        ids.push(row[this.options.keyName]); // 将选择行的id添加到id数组
      });

      if (!ids.length) {  // 如果没有选中行
        this.$mk.error("请选择行"); // 提示
        return;
      }

      let delParms = {};
      let url = this.options.actions.delete;


      if (url.indexOf('batchDelete') != -1) {
        delParms = {
          ids: ids
        }
      } else {
        delParms = {
          id: ids[0]
        }
      }

      this.$mk.confirm('您确定要删除吗？').then(type => { // 确认删除
        if (type == 'confirm') { // 如果确认删除
          this.$mk.post({
            url: url, // 请求删除数据地址
            loading: "删除中...", // 加载提示
            data: delParms,
            useBigInt: true
          }).then(() => { // 成功
            this.$mk.success("删除成功"); // 提示成功
            this.$refs.xGrid.commitProxy('query') // 提交搜索
          }).catch((a) => { // 失败
            this.$mk.error(a.data.msg); // 提示错误信息
          });
        }
      });
    },

    // 搜索
    onSearch2() {
      this.$refs.xGrid.commitProxy('query') // 提交搜索
    },

    onSearch(arg) {
      this.bindSearchData = arg;
      this.$refs.xGrid.commitProxy('query') // 提交搜索
    },

    gridReload() {
      this.$refs.xGrid.commitProxy('query')
    },

    getConfirmData() {
      let rows = this.$refs.xGrid.getCheckboxRecords();
      return rows;
    },
  },
  // 监听属性
  watch: {

  }
};

</script>
<style scoped lang="less">
.page-body {
  padding: 15px;
  background: @base-bg-color;
}

.gridPanel {
  height: calc(100vh - 220px);
}

.oplinks svg {
  width: 22px;
  height: 22px;
  margin: 0 5px 0 0;
}
</style>