<template>
  <a-space>
    <a-button @click="onToggleLoading">切换加载</a-button>
    <a-button @click="onToggleDisabled">切换禁用</a-button>
  </a-space>

  <JVxeTable
    ref="tableRef"
    stripe
    toolbar
    rowNumber
    rowSelection
    rowExpand
    resizable
    asyncRemove
    clickSelectRow
    :maxHeight="480"
    :checkboxConfig="{ range: true }"
    :disabledRows="{ input: ['text--16', 'text--18'] }"
    :loading="loading"
    :disabled="disabled"
    :columns="columns"
    :dataSource="dataSource"
    @removed="onJVxeRemove"
    @valueChange="handleValueChange"
  >
    <template #toolbarSuffix>
      <a-button @click="handleTableCheck">表单验证</a-button>
      <a-tooltip placement="top" title="获取值，忽略表单验证" :autoAdjustOverflow="true">
        <a-button @click="onGetData">获取数据</a-button>
      </a-tooltip>
      <a-tooltip placement="top" title="模拟加载1000条数据" :autoAdjustOverflow="true">
        <a-button @click="handleTableSet">设置值</a-button>
      </a-tooltip>
      <a-button @click="onGetSelData">获取选中数据</a-button>
      <a-button @click="onClearSel">清空选中</a-button>
      <a-button @click="onDelFirst">删除第一行数据</a-button>
      <a-button @click="onDelSel">删除选中数据</a-button>
    </template>

    <template #expandContent="props">
      <div style="padding: 20px">
        <span>Hello! My name is: {{ props.row.input }}!</span>
      </div>
    </template>

    <template #myAction="props">
      <a @click="onLookRow(props)">查看</a>
      <a-divider type="vertical" />
      <Popconfirm title="确定删除吗？" @confirm="onDeleteRow(props)">
        <a>删除</a>
      </Popconfirm>
    </template>
  </JVxeTable>
</template>

<script lang="ts" setup>
  import { ref } from 'vue';
  // noinspection ES6UnusedImports
  import { Popconfirm } from 'ant-design-vue';
  import { JVxeTypes, JVxeColumn, JVxeTableInstance } from '/@/components/jeecg/JVxeTable/types';
  import { useMessage } from '/@/hooks/web/useMessage';
  import { random } from 'lodash-es';
  import { buildUUID } from '/@/utils/uuid';
  import dayjs from 'dayjs';
  import { pushIfNotExist } from '/@/utils/common/compUtils';

  const { createMessage } = useMessage();
  const tableRef = ref<JVxeTableInstance>();
  const loading = ref(false);
  const disabled = ref(false);
  const columns = ref<JVxeColumn[]>([
    {
      title: 'ID',
      key: 'id',
      type: JVxeTypes.hidden,
    },
    {
      title: '不可编辑',
      key: 'noEdit',
      type: JVxeTypes.normal,
      width: 180,
      defaultValue: 'noEdit-new',
    },
    {
      title: '单行文本',
      key: 'input',
      type: JVxeTypes.input,
      width: 180,
      defaultValue: '',
      placeholder: '请输入${title}',
      validateRules: [
        {
          required: true, // 必填
          message: '请输入${title}', // 显示的文本
        },
        {
          pattern: /^[a-z|A-Z][a-z|A-Z\d_-]*$/, // 正则
          message: '必须以字母开头，可包含数字、下划线、横杠',
        },
        {
          unique: true,
          message: '${title}不能重复',
        },
        {
          handler({ cellValue, row, column }, callback, target) {
            // cellValue 当前校验的值
            // callback(flag, message) 方法必须执行且只能执行一次
            //          flag = 是否通过了校验，不填写或者填写 null 代表不进行任何操作
            //          message = 提示的类型，默认使用配置的 message
            // target 行编辑的实例对象
            if (cellValue === 'abc') {
              callback(false, '${title}不能是abc'); // false = 未通过校验
            } else {
              callback(true); // true = 通过验证
            }
          },
          message: '${title}默认提示',
        },
      ],
    },
    {
      title: '多行文本',
      key: 'textarea',
      type: JVxeTypes.textarea,
      width: 200,
    },
    {
      title: '数字',
      key: 'number',
      type: JVxeTypes.inputNumber,
      width: 80,
      defaultValue: 32,
      // 【统计列】sum = 求和、average = 平均值
      statistics: ['sum', 'average'],
    },
    {
      title: '下拉框',
      key: 'select',
      type: JVxeTypes.select,
      width: 180,
      // 下拉选项
      options: [
        { title: 'String', value: 'string' },
        { title: 'Integer', value: 'int' },
        { title: 'Double', value: 'double' },
        { title: 'Boolean', value: 'boolean' },
      ],
      // allowInput: true,
      allowSearch: true,
      placeholder: '请选择',
    },
    {
      title: '下拉框_字典',
      key: 'select_dict',
      type: JVxeTypes.select,
      width: 180,
      options: [],
      dictCode: 'sex',
      placeholder: '请选择',
    },
    {
      title: '下拉框_多选',
      key: 'select_multiple',
      type: JVxeTypes.selectMultiple,
      width: 205,
      options: [
        { title: 'String', value: 'string' },
        { title: 'Integer', value: 'int' },
        { title: 'Double', value: 'double' },
        { title: 'Boolean', value: 'boolean' },
      ],
      defaultValue: ['int', 'boolean'], // 多个默认项
      // defaultValue: 'string,double,int', // 也可使用这种方式
      placeholder: '多选',
    },
    {
      title: '下拉框_搜索',
      key: 'select_search',
      type: JVxeTypes.selectSearch,
      width: 180,
      options: [
        { title: 'String', value: 'string' },
        { title: 'Integer', value: 'int' },
        { title: 'Double', value: 'double' },
        { title: 'Boolean', value: 'boolean' },
      ],
    },
    {
      title: '日期时间',
      key: 'datetime',
      type: JVxeTypes.datetime,
      width: 200,
      defaultValue: '2019-04-30 14:52:22',
      placeholder: '请选择',
    },
    {
      title: '时间',
      key: 'time',
      type: JVxeTypes.time,
      width: 200,
      defaultValue: '14:52:22',
      placeholder: '请选择',
    },
    {
      title: '复选框',
      key: 'checkbox',
      type: JVxeTypes.checkbox,
      width: 100,
      customValue: ['Y', 'N'], // true ,false
      defaultChecked: false,
    },
    {
      title: '操作',
      key: 'action',
      type: JVxeTypes.slot,
      fixed: 'right',
      minWidth: 100,
      align: 'center',
      slotName: 'myAction',
    },
  ]);
  const dataSource = ref<any[]>([]);

  /* 随机生成数据 */
  function randomPage(current, pageSize, isLoading = false) {
    if (isLoading) {
      loading.value = true;
    }

    let randomDatetime = () => {
      let time = random(1000, 9999999999999);
      return dayjs(new Date(time)).format('YYYY-MM-DD HH:mm:ss');
    };

    let limit = (current - 1) * pageSize;

    let options = ['string', 'int', 'double', 'boolean'];

    let begin = Date.now();
    let values: any[] = [];
    for (let i = 0; i < pageSize; i++) {
      values.push({
        id: buildUUID(),
        noEdit: `noEdit-${limit + i + 1}`,
        input: `text-${limit + i + 1}`,
        textarea: `textarea-${limit + i + 1}`,
        number: random(0, 233),
        select: options[random(0, 3)],
        select_dict: random(1, 2).toString(),
        select_multiple: (() => {
          let length = random(1, 4);
          let arr = [];
          for (let j = 0; j < length; j++) {
            pushIfNotExist(arr, options[random(0, 3)]);
          }
          return arr.join(',');
        })(),
        select_search: options[random(0, 3)],
        datetime: randomDatetime(),
        checkbox: ['Y', 'N'][random(0, 1)],
      });
    }

    dataSource.value = values;
    let end = Date.now();
    let diff = end - begin;

    if (isLoading && diff < pageSize) {
      setTimeout(() => (loading.value = false), pageSize - diff);
    }
  }

  randomPage(0, 20, true);

  function onLookRow(props) {
    createMessage.success('请在控制台查看输出');
    // 参数介绍：
    // props.value          当前单元格的值
    // props.row            当前行的数据
    // props.rowId          当前行ID
    // props.rowIndex       当前行下标
    // props.column         当前列的配置
    // props.columnIndex    当前列下标
    // props.$table         vxe实例，可以调用vxe内置方法
    // props.target         JVXE实例，可以调用JVXE内置方法
    // props.caseId         JVXE实例唯一ID
    // props.scrolling      是否正在滚动
    // props.triggerChange  触发change事件，用于更改slot的值
    console.log('查看: ', { props });
  }

  async function onDeleteRow(props) {
    // 调用删除方法
    const res = await tableRef.value?.removeRows(props.row);
    if (res && res.rows.length > 0) {
      createMessage.success('删除成功');
    }
  }

  function handleValueChange(event) {
    console.log('handleValueChange.event: ', event);
  }

  /** 表单验证 */
  function handleTableCheck() {
    tableRef.value!.validateTable().then((errMap) => {
      if (errMap) {
        console.log('表单验证未通过：', { errMap });
        createMessage.error('验证未通过，请在控制台查看详细');
      } else {
        createMessage.success('验证通过');
      }
    });
  }

  /** 获取值，忽略表单验证 */
  function onGetData() {
    const values = tableRef.value!.getTableData();
    console.log('获取值:', { values });
    createMessage.success('获取值成功，请看控制台输出');
  }

  /** 模拟加载1000条数据 */
  function handleTableSet() {
    randomPage(1, 1000, true);
  }

  function onDelFirst() {
    const xTable = tableRef.value!.getXTable();
    const record = xTable.getTableData().fullData[0];
    tableRef.value!.removeRows(record);
  }

  function onDelSel() {
    const xTable = tableRef.value!.getXTable();
    xTable.removeCheckboxRow();
  }

  function onGetSelData() {
    createMessage.info('请看控制台');
    console.log(tableRef.value!.getSelectionData());
  }

  function onClearSel() {
    tableRef.value!.clearSelection();
  }

  function onToggleLoading() {
    loading.value = !loading.value;
  }

  function onToggleDisabled() {
    disabled.value = !disabled.value;
  }

  function doDelete(deleteRows) {
    return new Promise((resolve) => {
      let rowId = deleteRows.map((row) => row.id);
      console.log('删除 rowId: ', rowId);
      setTimeout(() => resolve(true), 1500);
    });
  }

  /** 异步删除示例 */
  async function onJVxeRemove(event) {
    const hideLoading = createMessage.loading('删除中…', 0);
    try {
      // 1. 向后台传递 event.deleteRows 以删除
      let flag = await doDelete(event.deleteRows);
      if (flag) {
        // 注：如果启用了表格的 loading 状态，则必须先停止再删除，否则会导致无法从表格上删除数据
        // 2. 调用 event.confirmRemove 方法确认删除成功
        await tableRef.value!.removeSelection();
        // await event.confirmRemove()
        createMessage.success('删除成功！');
      } else {
        // 3. 若删除失败，不调用 event.confirmRemove() 方法就不会删除数据
        createMessage.warn('删除失败！');
      }
    } finally {
      hideLoading();
    }
  }
</script>
