<template>
  <el-skeleton :animated="true" :loading="initLoading" :rows="20" :style="showTableForm ? 'padding: 20px;' : 'padding: 0px 20px 20px 0px;'"
               :throttle="500">
    <!-- 查询表单区域 -->
    <slot name="queryForm">
      <easy-data-form v-if="showTableForm" ref="EasyDataForm" v-bind="bindFormProps()"
                      @keyup.enter.native="searchQuery">
        <!-- 字段插槽 - 头部添加 -->
        <template v-slot:formHeader="data">
          <slot name="easyFormHeader" v-bind="data"></slot>
        </template>

        <!-- 字段插槽 - 重置 -->
        <template v-for="name in FormSlotNames" v-slot:[name]="data">
          <slot :name="name" v-bind="data"></slot>
        </template>

        <!-- 字段插槽 - 尾部添加 -->
        <template v-slot:formFooter="data">
          <slot name="easyFormFooter" v-bind="data"></slot>
        </template>
      </easy-data-form>
    </slot>

    <!-- 操作按钮区域 -->
    <slot name="operate">
      <ed-form-action v-if="showAction" v-model="actionStatus" :is-operate="isOperate" v-bind="actionProps"
                      @add="showEasyDataModal" @export="exportData" @query="searchQuery"
                      @reset="searchReset">
        <!-- 按钮区域插槽 - 插入 -->
        <template v-for="item in renderFormSlot()" #[item]="data">
          <slot :name="item" v-bind="getFormActionSlot(data)"></slot>
        </template>
      </ed-form-action>
    </slot>

    <!-- table区域 -->
    <ed-table ref="BasicTable" v-loading="tableLoading" :pagination.sync="showPagination ? pagination : undefined"
              class="basicTable" v-bind="bindTableProps()"
              @change="handleTableChange" @current-change="handleCurrentChange" @selection-change="handleSelectionChange">
      <!-- 索引列插槽 -->
      <template v-slot:indexColumn>
        <slot name="indexColumn"></slot>
      </template>

      <!-- 索引列内部插槽 -->
      <template v-slot:customRow="scope">
        <slot name="diyExpand" v-bind="{ self, scope, ...scope }">
          <ed-json-viewer v-if="columnType==='expand'" :value="scope.row" copyable expanded></ed-json-viewer>
        </slot>
      </template>

      <!-- 展示列插槽 -->
      <template v-for="name in ColumnSlotNames" v-slot:[name]="scope">
        <slot :name="name" v-bind="scope"></slot>
      </template>

      <!-- 操作列插槽 -->
      <template v-slot:operate="scope">
        <slot name="tableSlot" v-bind="{ self, scope, ...scope }">
          <el-button size="mini" type="text" @click="handlerDetail(scope.row, scope.$index)">查看</el-button>
          <el-divider direction='vertical'></el-divider>
          <el-button size="mini" type="text" @click="handlerEdit(scope.row, scope.$index)">编辑</el-button>
          <el-divider direction='vertical'></el-divider>
          <el-popconfirm title="确定删除数据吗？" @confirm="handlerDelete(scope.row.id)">
            <el-button slot="reference" size="mini" style="color: red" type="text">删除</el-button>
          </el-popconfirm>
        </slot>
      </template>
    </ed-table>
    <BasicModal ref="BasicModal" :controlConfig="controlConfig" :dataSourceName="dataSourceName" :descColumns="columns"
                :loading="modalLoading"
                @ok="submitModalForm"></BasicModal>
  </el-skeleton>
</template>

<script>
import useTable       from './hooks/useTable'
import useForm        from './hooks/useForm'
import useEmits       from './hooks/useEmits'
import EasyDataMixins from '../mixins/EasyDataMixins'
import Props          from './Props'
import BasicModal     from './components/BasicModal'
import EdFormAction   from './components/FormAction'
import {getVarType}   from '../../utils/utils'
import {setFormData}  from "../../utils/useBusiness";
import {formatDate}   from "../../utils/dateUtils";
import {DefaultUrl}   from "../../api/easyData";

/**
 * EasyDataList组件
 * - 示例
 *
 * ```vue
 * <easy-data-list ref="EasyDataList" :columnType="columnType" :dataSourceName="dataSourceName" :diy-colums="diyColums"
 *                 :form-props="formProps" model="list" @editColumns="editColumns">
 * </easy-data-list>
 * ```
 * 详细用法参考下方链接
 *
 * [EasyDataList组件使用示例](./web-comp/ExampleEasyDataListCode.md)
 *
 * [](./EasyDataListProps.md ':include')
 *
 * ## Props
 *
 * | Name               | Type                    | Description           |
 * | ------------------ | ----------------------- | --------------------- |
 * | `data-source-name` | `String`                | 数据源名称                 |
 * | `view-id`          | `String`                | 视图ID,用于显示不同视图         |
 * | `biz-params`       | `Object`                | 业务请求参数,仅模板使用          |
 * | `form-data`        | `Array` &#124; `Object` | 表单数据默认值,新增接口提交数据会自动带上 |
 * | `extra-params`     | `Object`                | 额外请求参数,仅模板使用          |
 * | `pass-module-ids`  | `Array`                 | 数据源传递                 |
 * | `module-prop`      | `Object`                | 模块属性 模块使用自定义属性        |
 *
 * ## Slots(插槽)
 *
 * | Name             | Description   |
 * |------------------|---------------|
 * | `tableSlot`      | 列表右侧操作栏插槽     |
 * | `extra`          | 在列表上方按钮区域追加按钮 |
 * | `resetBefore`    | 重置按钮之前追加      |
 * | `queryBefore`    | 查询按钮之前追加      |
 * | `exportBefore`   | 导出按钮之前追加      |
 * | `addBefore`      | 新增按钮之前追加      |
 * | `easyFormFooter` | 查询表单区域插槽      |
 *
 * [](./useTable.md ':include')
 *
 */
export default {
  name: "EasyDataList",
  components: {BasicModal, EdFormAction},
  mixins: [useTable, useForm, useEmits, EasyDataMixins],
  props: Props,
  data() {
    return {
      self: this,
      // 数据源配置属性
      controlConfig: {},
      // 表单属性对象
      controlProp: {},
      // 初始化loading
      modalLoading: false,
      // form插槽
      FormSlotNames: [],
      // 是否显示展开收起按钮
      isOperate: false,
      // 展开收起状态
      actionStatus: "",
      // table 插槽
      ColumnSlotNames: [],
      defaultHttpUrl: {
        insertUrl: DefaultUrl.insertData, // 表单更新地址
        updateUrl: DefaultUrl.updateData, // table 数据请求地址
        pageUrl: DefaultUrl.page, //分页查询地址
        deleteUrl: DefaultUrl.deleteData,
        exportDataList: DefaultUrl.exportDataList
      }
    }
  },
  watch: {
    dataSourceName: {
      immediate: true,
      async handler(newVal, oldVal) {
        if (newVal && newVal !== oldVal) {
          this.initLoading = true
          this.initLoading = true
          const {dataSource, controlProps, controlInfos} = await this.initControls()
          this.initLoading = false
          this.$set(this.controlConfig, 'dataSource', dataSource)
          this.$set(this.controlConfig, 'controlProps', controlProps)
          this.$set(this.controlConfig, 'controlInfos', controlInfos)

          // 组装列数据
          this.columns = this.columns.length === 0 ? this.getColumns(controlInfos, controlProps) : this.columns
          this.initSlotNames()

          //等待查询表单加载完成，并初始化默认数据后。
          if (this.autoQuery) await this.searchQuery()

          // 初始化按钮组状态
          this.setFormActionProps()
        }
      }
    },
    actionStatus(newVal, oldVal) {
      if (newVal) {
        let formDom = this.$refs.EasyDataForm.$refs.EasyDataForm.$el
        let height = formDom[0]?.offsetHeight + 18
        this.formHeight = newVal === 'retract' && formDom[0] ? `${height}px` : 'auto';
      }
    },
    formParams: {
      deep: true,
      immediate: true,
      handler(newVal, oldVal) {
        if (newVal) {
          for (let key in newVal) {
            this.formKeyInfo[key] = newVal[key]
          }
        }
      }
    },
    formData: {
      deep: true,
      immediate: true,
      handler(newVal, oldVal) {
        if (newVal && getVarType(newVal) === 'array' && newVal.length > 0 && this.controlConfig) {
          const {controlInfos} = this.controlConfig
          this.tableData = setFormData(newVal, controlInfos, this)
        }
      }
    },
    httpUrl: {
      deep: true,
      immediate: true,
      handler(newVal, oldVal) {
        if (newVal && Object.keys(newVal).length < 5) {
          this.$emit('update:httpUrl', Object.assign({}, this.defaultHttpUrl, newVal))
        }
      }
    }
  },
  computed: {
    // 是否显示表达操作按钮区域
    showAction() {
      return getVarType(this.actionProps) === 'boolean' ? this.actionProps : true;
    }
  },

  methods: {
    // 初始化插槽列表
    initSlotNames() {
      // form表单插槽项
      this.controlInfos.map(control => {
        this.FormSlotNames.push(control.controlName)
      })

      // table列插槽项
      this.columns.map(column => {
        let name = column.prop.includes('keyInfo') ? column.prop.split('.')[1] : column.prop
        this.ColumnSlotNames.push(name + 'Column')
      })
    },

    // 设置按钮组属性
    setFormActionProps() {
      let height = this.$refs.EasyDataForm.$refs.EasyDataForm.$el.offsetHeight
      this.isOperate = this.bindFormProps().inline && height > 55
      if (this.isOperate) {
        this.actionStatus = height > 55 ? 'retract' : 'expand'
      }
    },

    /**
     * @private
     * @param val
     */
    handleCurrentChange(val) {
      /**
       * @private
       * @event handleCurrentChange
       */
      this.$emit('handleCurrentChange', val)
    },

    /**
     * @private
     * @param val
     */
    handleSelectionChange(val) {
      this.$emit('selection-change', val)
    },

    /**
     * @name submitModalForm
     * @param params
     * @param submitUrl
     * @return {Promise<void>}
     */
    async submitModalForm(params, submitUrl) {
      this.modalLoading = true
      const res = await this.$EdFrame.postAction(submitUrl, params).finally(() => {
        this.modalLoading = false
      });
      this.modalLoading = false
      if (res.success) {
        await this.loadTableData()
        this.$refs.BasicModal.close()
        this.$message.success(res.msg)
      } else {
        this.$message.error(res.msg)
      }
    },

    /**
     * @name showEasyDataModal
     */
    showEasyDataModal(viewId) {
      this.$refs.BasicModal.showModal({
        formData: this.formData,
        isDescribe: false,
        submitUrl: this.httpUrl.insertUrl,
        title: '新增-' + this.dataSource.remark,
        useControlConfig: !viewId,
        viewId: viewId
      })
    },
    /**
     * 导出数据
     */
    exportData() {
      this.$EdFrame.downFilePost(this.httpUrl.exportDataList, this.getQueryParams()).then((res) => {
        const date = formatDate(new Date(), 'yyyy-MM-dd hh:mm:ss')
        const fileName = this.dataSource.remark + date + '.xlsx'
        let url = window.URL.createObjectURL(new Blob([res]));
        let link = document.createElement('a');
        link.style.display = 'none';
        link.href = url;
        link.setAttribute('download', fileName);
        document.body.appendChild(link);
        link.click();
        //释放内存
        window.URL.revokeObjectURL(link.href)
      })
    },
    /**
     * @name getFormActionSlot
     * @return {{form: {}}}
     * @description 按钮区slot传参
     */
    getFormActionSlot(data) {
      return {
        ...data,
        form: this.$refs.EasyDataForm.formModel,
        self: this.$refs.EasyDataForm.self
      }
    },
  }
}

</script>

<style lang="scss" scoped>
@import "../../style/index.scss";
</style>
