<!-- 文件预览 -->
<template>
  <div class="file-table">
    <BaseTable
      ref="fileTableRef"
      v-bind="{
        ...$attrs,
        ...(needContextMenu
          ? {
              'menu-config': menuConfig,
              'row-class-name': rowClassName,
              'onMenu-click': handleMenuClick,
              'onCell-menu': handleContextMenu,
            }
          : {}),
      }"
      fullHeight
      :actionList="allActionList"
    >
      <!-- 给文档打标签,需要配置fileType字段 -->
      <template #[fileTagField]="{ row }">
        <FileTypeChange
          v-model="row[fileTagField]"
          :id="row[fileIdField] || row.fileId || row.uuid"
        />
      </template>
      <!-- baseTable插槽 -->
      <template v-for="(_, name) in $slots" #[name]="slotData">
        <slot :name="name" v-bind="slotData"></slot>
      </template>
    </BaseTable>
    <FilePreview
      v-model="previewVisible"
      :fileId="previewFileId"
      :type="currentNeedPreviewType || 'kkFile'"
    />
  </div>
</template>

<script lang="ts" setup>
import { ref, computed, onMounted, onBeforeUnmount } from 'vue';
import BaseTable from '@/components/common/table/baseTable.vue';
import FilePreview from '@/components/common/filePreview/index.vue';
import { downloadFileById, isAcceptFileType } from '@/utils/file';
import FileTypeChange from '@/components/common/fileTable/fileTypeChange.vue';
import { ElMessage } from 'element-plus';
import { dataDelFileApi } from '@/api/data/data';

const props = defineProps({
  actionList: {
    type: Array,
    default: () => [],
  },
  // 操作栏默认列表，不传默认需要所有
  defaultActions: {
    type: Array,
    default: () => ['preview', 'download', 'delete'],
  },
  // 预览方式  如果想用onlyOffice，则 fileNameField 必传
  previewType: {
    type: String,
    default: 'kkFile',
  },
  // 文件名的字段 用后缀来判断是否支持用 onlyOffice 预览，当previewType为onlyOffice时必传
  fileNameField: {
    type: String,
    default: '',
  },
  // 文件id的字段， 1）用于下载，预览； 2）用于在右键时高亮当前行, 默认查找顺序：id -> fileId -> uuid
  fileIdField: {
    type: String,
    default: 'id',
  },
  // 是否需要右键菜单，默认不需要
  needContextMenu: {
    type: Boolean,
    default: false,
  },
  // 文件标签字段
  fileTagField: {
    type: String,
    default: 'fileType',
  },
});

const fileTableRef = ref();
const previewVisible = ref(false);
const previewFileId = ref('');
const currentNeedPreviewType = ref(''); // 当前真实需要预览的方式

// #region ---------------------------操作栏---------------------------
// 默认的操作栏, 如果有业务判断，就在业务组件内部写
const defaultActionList = computed(() => [
  ...(props.defaultActions?.includes('preview')
    ? [
        {
          title: '预览',
          type: 'primary',
          click: (row: any) => {
            // 如果外部没有传previewType或者传的是kkfile，则不需要额外处理；
            // 如果传的是onlyOffice,那么需要把文件名字段也传过来，因为onlyOffice需要判断文件类型 isAcceptFileType
            if (props.previewType === 'onlyOffice' && props.fileNameField) {
              currentNeedPreviewType.value = isAcceptFileType(
                row[props.fileNameField],
                'onlyOffice'
              )
                ? 'onlyOffice'
                : 'kkFile';
            }
            // 文件唯一标识 [id -> fileId -> uuid], 如果传了，优先用传过来的，没传就按这个顺序找
            const fileId = row[props.fileIdField] || row.fileId || row.uuid;
            previewFileId.value = fileId;
            previewVisible.value = true;
          },
        },
      ]
    : []),
  ...(props.defaultActions?.includes('download')
    ? [
        {
          title: '下载',
          type: 'primary',
          click: (row: any) => downloadFile(row[props.fileIdField] || row.fileId || row.uuid),
        },
      ]
    : []),
  ...(props.defaultActions?.includes('delete')
    ? [
        {
          title: '删除',
          type: 'danger',
          click: (row: any) => {
            deleteFileFun(row[props.fileIdField] || row.fileId || row.uuid);
          },
        },
      ]
    : []),
]);

const deleteFileFun = async (id: number) => {
  const res: any = await dataDelFileApi({ delFileId: id });
  if (res.code === 200) {
    ElMessage.success('删除成功');
    fileTableRef.value.resetFun();
  }
};
// 展示的操作栏
const allActionList = computed(() => {
  return [...defaultActionList.value, ...props.actionList];
});
// 文件下载
const downloadFile = (id: any) => {
  downloadFileById(id);
};
// #endregion

// #region ---------------------------右键菜单模块---------------------------
// 当前右键操作的行
const currentHighlightRowId = ref('');
const menuConfig = ref({
  enabled: true,
  body: {
    options: [
      [
        { code: 'copy', name: '复制', prefixConfig: { icon: 'vxe-icon-copy' } },
        { code: 'edit', name: '编辑', prefixConfig: { icon: 'vxe-icon-edit' } },
        { code: 'delete', name: '删除', prefixConfig: { icon: 'vxe-icon-delete' } },
      ],
    ],
  },
});

const handleContextMenu = ({ row, $event }: { row: any; $event: any }) => {
  $event.preventDefault();
  currentHighlightRowId.value = row[props.fileIdField] || row.fileId || row.uuid; // 每行的唯一标识
};
// 添加行样式计算
const rowClassName = ({ row }: { row: any }) => {
  const rowId = row[props.fileIdField] || row.fileId || row.uuid;
  return currentHighlightRowId.value === rowId && rowId ? 'highlight-row' : '';
};

const handleMenuClick = ({ menu, row }: { menu: any; row: any }) => {
  // 根据点击的菜单项执行不同操作
  switch (menu.code) {
    case 'copy':
      console.info('copy', row);
      break;
    case 'edit':
      console.info('edit', row);
      break;
    case 'delete':
      console.info('delete', row);
  }
  currentHighlightRowId.value = '';
};
// 全局点击处理
const handleGlobalClick = (event: any) => {
  // 检查点击是否在菜单内
  const menuEl = document.querySelector('.vxe-table--context-menu-wrapper');
  if (menuEl && !menuEl.contains(event.target)) {
    currentHighlightRowId.value = '';
  }
};
// 监听全局点击事件
onMounted(() => {
  document.addEventListener('click', handleGlobalClick);
});

onBeforeUnmount(() => {
  document.removeEventListener('click', handleGlobalClick);
});
// #endregion

// ---------------------------透传 baseTable 的所有暴露属性和方法---------------------------
defineExpose({
  ...Object.fromEntries(
    [
      'tableData',
      'tableRef',
      'resetFun',
      'setDataFun',
      'getSearchParamsFun',
      'getSearchParamByKeyFun',
      'setSearchParamsFun',
      'setSearchParamByKeyFun',
      'setOptionsFun',
      'getTableDataFun',
    ].map((method) => [method, (...args: any[]) => fileTableRef.value?.[method](...args)])
  ),
});
</script>

<style lang="scss" scoped>
.file-table {
  height: 100%;
}
.file-name {
  display: flex;
  align-items: center;
  .img {
    width: 20px;
    height: 20px;
    margin-right: 8px;
  }
}
</style>
<style lang="scss">
.file-table {
  .highlight-row {
    background-color: var(--el-color-primary-light-9) !important;
  }
}
</style>
