<script setup lang="tsx">
import { computed, markRaw, onMounted, reactive, ref, watch } from 'vue';
import { ElButton, ElMessageBox, ElTag } from 'element-plus';
import dayjs from 'dayjs';
import {
  batchDownloadPerformanceSheets,
  deletePerformanceSheet,
  downloadPerformanceSheet,
  exportPerformanceSheets,
  fetchGetDeptSelfAndChildren,
  fetchGetDirectSubordinates,
  fetchGetMyProfileDetail,
  fetchGetMySubordinateTree,
  fetchPerformanceSheetPage,
  fetchPerformanceSheetStatusDict,
  fetchTeamPerformanceSummary,
  formatToYYYYMM,
  resendPerformanceSheet,
  sendPerformanceSheet
} from '@/service/api';
import { useAuthStore } from '@/store/modules/auth';
import { useAuth } from '@/hooks/business/auth';
import { useUIPaginatedTable } from '@/hooks/common/table';
import SubordinateSelector from '@/components/custom/subordinate-selector.vue';
import TeamContextPanel from '@/components/custom/team-context-panel.vue';
import BusinessTableActionCell, { type BusinessTableAction } from '@/components/custom/business-table-action-cell';
import {
  type TeamViewContext,
  type TeamViewMode,
  collectSubordinateUserIds,
  findSubordinateNode
} from '../shared/team-dashboard';
import PerformanceActionDialog from './modules/performance-action-dialog.vue';
import PerformanceExcelEditorDrawer from './modules/performance-excel-editor-drawer.vue';
import PerformanceRecordDialog from './modules/performance-record-dialog.vue';
import PerformanceSearch from './modules/performance-search.vue';
import PerformanceSummary from './modules/performance-summary.vue';
import PerformanceTemplateDialog from './modules/performance-template-dialog.vue';
import {
  PerformancePermission,
  createDefaultPeriodMonth,
  downloadBlob,
  formatDateTime,
  formatScore,
  getPerformanceStatusLabel,
  getPerformanceStatusOptions,
  getSheetExportName,
  resolvePerformanceStatusTagType
} from './modules/performance-shared';
import IconMdiCheckCircleOutline from '~icons/mdi/check-circle-outline';
import IconMdiCloseCircleOutline from '~icons/mdi/close-circle-outline';
import IconMdiDeleteOutline from '~icons/mdi/delete-outline';
import IconMdiDownloadOutline from '~icons/mdi/download-outline';
import IconMdiEyeOutline from '~icons/mdi/eye-outline';
import IconMdiFileDocumentEditOutline from '~icons/mdi/file-document-edit-outline';
import IconMdiPencilOutline from '~icons/mdi/pencil-outline';
import IconMdiSendOutline from '~icons/mdi/send-outline';

defineOptions({ name: 'MyPerformance' });

type PerformanceSheetPageResponse = Awaited<ReturnType<typeof fetchPerformanceSheetPage>>;

function createSearchParams(): Api.Performance.Sheet.SearchParams {
  return {
    pageNo: 1,
    pageSize: 10,
    employeeIds: undefined,
    periodMonthRange: undefined,
    employeeId: undefined,
    employeeName: undefined,
    employeeDeptId: undefined,
    employeeDeptName: undefined,
    managerId: undefined,
    managerName: undefined,
    statusCode: undefined
  };
}

function transformPageResult(response: PerformanceSheetPageResponse, pageNo: number, pageSize: number) {
  if (!response.error && response.data) {
    return {
      data: response.data.list,
      pageNum: pageNo,
      pageSize,
      total: response.data.total
    };
  }

  return {
    data: [],
    pageNum: 1,
    pageSize,
    total: 0
  };
}

const { hasAuth } = useAuth();
const authStore = useAuthStore();
const searchParams = reactive(createSearchParams());
const teamViewMode = ref<TeamViewMode>('self');
const subordinateTreeLoading = ref(false);
const subordinateTree = ref<Api.SystemManage.MySubordinateTreeNode | null>(null);
const selectedSubordinateUserId = ref<string | null>(null);
const teamSummaryLoading = ref(false);
const teamSummary = ref<Api.Performance.Team.Summary | null>(null);
const selectedRows = ref<Api.Performance.Sheet.Sheet[]>([]);
const currentRow = ref<Api.Performance.Sheet.Sheet | null>(null);
const deptOptions = ref<Array<{ label: string; value: string }>>([]);
const directSubordinateOptions = ref<Array<{ label: string; value: string }>>([]);
const statusOptions = ref<Array<{ label: string; value: string }>>([]);
const currentDeptId = ref<string>('');

const templateVisible = ref(false);
const excelVisible = ref(false);
const excelMode = ref<'view' | 'edit' | 'create'>('view');
const actionVisible = ref(false);
const actionType = ref<'confirm' | 'reject'>('confirm');
const recordVisible = ref(false);

const exporting = ref(false);
const currentUserId = computed(() => authStore.userInfo.userId || '');
const rowActionLoadingKey = ref('');

const ACTION_ICON_MAP = {
  view: markRaw(IconMdiEyeOutline),
  edit: markRaw(IconMdiPencilOutline),
  send: markRaw(IconMdiSendOutline),
  confirm: markRaw(IconMdiCheckCircleOutline),
  reject: markRaw(IconMdiCloseCircleOutline),
  export: markRaw(IconMdiDownloadOutline),
  delete: markRaw(IconMdiDeleteOutline),
  response: markRaw(IconMdiFileDocumentEditOutline)
};

const canUseTeamDashboard = computed(() => hasAuth(PerformancePermission.TeamDashboard));
const canCreate = computed(() => hasAuth(PerformancePermission.SheetCreate));
const canUpdate = computed(() => hasAuth(PerformancePermission.SheetUpdate));
const canDelete = computed(() => hasAuth(PerformancePermission.SheetDelete));
const canConfirm = computed(() => hasAuth(PerformancePermission.SheetConfirm));
const canReject = computed(() => hasAuth(PerformancePermission.SheetReject));
const canExport = computed(() => hasAuth(PerformancePermission.SheetExport));
const canManageTemplate = computed(
  () => hasAuth(PerformancePermission.TemplateQuery) || hasAuth(PerformancePermission.TemplateUpdate)
);
const isTeamMode = computed(() => teamViewMode.value === 'team');
const allSubordinateUserIds = computed(() => collectSubordinateUserIds(subordinateTree.value));
const subordinateOptions = computed(() => {
  const options: Array<{ label: string; value: string }> = [];

  const walk = (nodes?: Api.SystemManage.MySubordinateTreeNode[] | null) => {
    nodes?.forEach(node => {
      options.push({ label: node.userNickname, value: node.userId });
      walk(node.children ?? null);
    });
  };

  walk(subordinateTree.value?.children ?? null);
  return options;
});
const selectedSubordinateNode = computed(() =>
  findSubordinateNode(subordinateTree.value, selectedSubordinateUserId.value)
);
const formattedPeriodMonthStart = computed(
  () => formatToYYYYMM(searchParams.periodMonthRange?.[0]) || createDefaultPeriodMonth()
);
const formattedPeriodMonthEnd = computed(
  () => formatToYYYYMM(searchParams.periodMonthRange?.[1]) || createDefaultPeriodMonth()
);
const isRootSelected = computed(() => Boolean(isTeamMode.value && selectedSubordinateNode.value?.isRoot));
const selectedTeamLabel = computed(() => {
  if (!isTeamMode.value) return '我自己';
  if (!selectedSubordinateNode.value) return '--';

  return selectedSubordinateNode.value.isRoot ? '全部下属' : selectedSubordinateNode.value.userNickname;
});
const teamContext = computed<TeamViewContext | null>(() => {
  if (!canUseTeamDashboard.value) return null;

  return {
    mode: teamViewMode.value,
    selectedUserId: selectedSubordinateUserId.value,
    selectedUserIds:
      isTeamMode.value && selectedSubordinateUserId.value && !isRootSelected.value
        ? [selectedSubordinateUserId.value]
        : [],
    isRootSelected: isRootSelected.value,
    allSubordinateUserIds: allSubordinateUserIds.value,
    selectedLabel: selectedTeamLabel.value
  };
});
const currentEmployeeIds = computed(() => {
  if (!isTeamMode.value) return undefined;
  if (isRootSelected.value) return [];

  return teamContext.value?.selectedUserIds ?? [];
});
const resolvedEmployeeIds = computed(() => {
  if (!isTeamMode.value) {
    return undefined;
  }

  if (searchParams.employeeId) {
    return [searchParams.employeeId];
  }

  return currentEmployeeIds.value;
});

const { columns, columnChecks, data, loading, getDataByPage, mobilePagination, reloadColumns } = useUIPaginatedTable<
  PerformanceSheetPageResponse,
  Api.Performance.Sheet.Sheet
>({
  paginationProps: {
    currentPage: searchParams.pageNo,
    pageSize: searchParams.pageSize
  },
  api: () =>
    fetchPerformanceSheetPage({
      ...searchParams,
      employeeIds: resolvedEmployeeIds.value,
      employeeId: undefined
    }),
  transform: response => transformPageResult(response, searchParams.pageNo ?? 1, searchParams.pageSize ?? 10),
  onPaginationParamsChange: params => {
    searchParams.pageNo = params.currentPage ?? 1;
    searchParams.pageSize = params.pageSize ?? 10;
  },
  columns: () => {
    const baseColumns: UI.TableColumn<Api.Performance.Sheet.Sheet>[] = [
      { prop: 'selection', type: 'selection', width: 48 },
      { prop: 'index', type: 'index', label: '序号', width: 64 },
      { prop: 'periodMonth', label: '绩效月份', minWidth: 110 }
    ];

    if (isTeamMode.value) {
      baseColumns.push({ prop: 'employeeName', label: '下属', minWidth: 110, showOverflowTooltip: true });
    }

    baseColumns.push(
      { prop: 'managerName', label: '直属上级', minWidth: 110, showOverflowTooltip: true },
      { prop: 'employeeDeptName', label: '部门', minWidth: 110, showOverflowTooltip: true },
      {
        prop: 'statusCode',
        label: '状态',
        minWidth: 100,
        align: 'center',
        formatter: row => (
          <ElTag type={resolvePerformanceStatusTagType(row.statusCode)}>
            {getPerformanceStatusLabel(row.statusCode, row.statusName)}
          </ElTag>
        )
      },
      {
        prop: 'actualScoreTotal',
        label: '实际得分',
        minWidth: 100,
        formatter: row => formatScore(row.actualScoreTotal)
      },
      // {
      //   prop: 'baseScoreTotal',
      //   label: '基础得分',
      //   width: 100,
      //   align: 'right',
      //   formatter: row => formatScore(row.baseScoreTotal)
      // },
      // {
      //   prop: 'extraScoreTotal',
      //   label: '附加得分',
      //   width: 100,
      //   align: 'right',
      //   formatter: row => formatScore(row.extraScoreTotal)
      // },
      {
        prop: 'sentTime',
        label: '发送时间',
        minWidth: 150,
        formatter: row => formatDateTime(row.sentTime)
      },
      {
        prop: 'confirmedTime',
        label: '确认时间',
        minWidth: 150,
        formatter: row => formatDateTime(row.confirmedTime)
      },
      // {
      //   prop: 'updateTime',
      //   label: '更新时间',
      //   width: 150,
      //   formatter: row => formatDateTime(row.updateTime)
      // },
      {
        prop: 'operate',
        label: '操作',
        width: 190,
        align: 'center',
        fixed: 'right',
        formatter: row => <BusinessTableActionCell actions={getRowActions(row)} variant="icon" />
      }
    );

    return baseColumns;
  }
});

const totalCount = computed(() => mobilePagination.value.total || data.value.length);

function getRowActions(row: Api.Performance.Sheet.Sheet): BusinessTableAction[] {
  const actions: BusinessTableAction[] = [
    {
      key: 'view',
      label: '查看',
      buttonType: 'primary',
      icon: ACTION_ICON_MAP.view,
      onClick: () => openExcel(row, 'view')
    }
  ];

  if (canExport.value && row.fileId) {
    actions.push({
      key: 'export',
      label: '导出',
      buttonType: 'info',
      icon: ACTION_ICON_MAP.export,
      disabled: rowActionLoadingKey.value === `export:${row.id}`,
      onClick: () => handleDownload(row)
    });
  }

  if (isTeamMode.value) {
    const isDirectManager = Boolean(currentUserId.value) && row.managerId === currentUserId.value;

    if (isDirectManager && canUpdate.value && ['draft', 'rejected'].includes(row.statusCode)) {
      actions.push({
        key: 'edit',
        label: '编辑',
        buttonType: 'primary',
        icon: ACTION_ICON_MAP.edit,
        onClick: () => openExcel(row, 'edit')
      });
      actions.push({
        key: row.statusCode === 'rejected' ? 'resend' : 'send',
        label: row.statusCode === 'rejected' ? '重新发送' : '发送',
        buttonType: 'success',
        icon: ACTION_ICON_MAP.send,
        disabled: rowActionLoadingKey.value === `send:${row.id}`,
        onClick: () => handleSend(row)
      });
    }

    if (isDirectManager && canDelete.value && row.statusCode === 'draft') {
      actions.push({
        key: 'delete',
        label: '删除',
        buttonType: 'danger',
        icon: ACTION_ICON_MAP.delete,
        disabled: rowActionLoadingKey.value === `delete:${row.id}`,
        onClick: () => handleDelete(row)
      });
    }
  } else if (row.statusCode === 'sent') {
    if (canConfirm.value) {
      actions.push({
        key: 'confirm',
        label: '确认',
        buttonType: 'success',
        icon: ACTION_ICON_MAP.confirm,
        onClick: () => openAction(row, 'confirm')
      });
    }
    if (canReject.value) {
      actions.push({
        key: 'reject',
        label: '退回',
        buttonType: 'danger',
        icon: ACTION_ICON_MAP.reject,
        onClick: () => openAction(row, 'reject')
      });
    }
  }

  actions.push({
    key: 'response-record',
    label: '反馈历史',
    buttonType: 'info',
    icon: ACTION_ICON_MAP.response,
    onClick: () => openRecord(row)
  });

  return actions;
}

function resetSearchParams() {
  const pageSize = searchParams.pageSize ?? 10;
  Object.assign(searchParams, createSearchParams(), { pageSize });
  reloadTable(1);
  loadTeamSummary();
}

function handleSearch() {
  reloadTable(1);
  loadTeamSummary();
}

async function reloadTable(page = searchParams.pageNo ?? 1) {
  await getDataByPage(page);
}

function createExportParams(): Api.Performance.Sheet.SearchParams {
  const { pageNo: _pageNo, pageSize: _pageSize, ...params } = searchParams;

  return {
    ...params,
    employeeIds: resolvedEmployeeIds.value ?? undefined,
    employeeId: undefined
  };
}

function handleSelectionChange(rows: Api.Performance.Sheet.Sheet[]) {
  selectedRows.value = rows;
}

function openExcel(row: Api.Performance.Sheet.Sheet, mode: 'view' | 'edit') {
  currentRow.value = row;
  excelMode.value = mode;
  excelVisible.value = true;
}

function openCreateExcel() {
  currentRow.value = null;
  excelMode.value = 'create';
  excelVisible.value = true;
}

function openAction(row: Api.Performance.Sheet.Sheet, type: 'confirm' | 'reject') {
  currentRow.value = row;
  actionType.value = type;
  actionVisible.value = true;
}

function openRecord(row: Api.Performance.Sheet.Sheet) {
  currentRow.value = row;
  recordVisible.value = true;
}

async function handleDownload(row: Api.Performance.Sheet.Sheet) {
  rowActionLoadingKey.value = `export:${row.id}`;
  const { error, data: blob } = await downloadPerformanceSheet(row.id);
  rowActionLoadingKey.value = '';

  if (error || !blob) return;

  downloadBlob(blob, getSheetExportName(row));
}

async function handleExportSelected() {
  if (!selectedRows.value.length) {
    window.$message?.warning('请选择要导出的绩效表');
    return;
  }

  exporting.value = true;
  const { error, data: blob } = await batchDownloadPerformanceSheets({
    ids: selectedRows.value.map(item => item.id)
  });
  exporting.value = false;

  if (error || !blob) return;

  downloadBlob(blob, `绩效表_导出选中_${dayjs().format('YYYY-MM-DD')}.xlsx`);
}

async function handleExportAll() {
  exporting.value = true;
  const { error, data: blob } = await exportPerformanceSheets(createExportParams());
  exporting.value = false;

  if (error || !blob) return;

  downloadBlob(blob, `绩效表_导出全部_${dayjs().format('YYYY-MM-DD')}.xlsx`);
}

async function handleExportCommand(command: 'selected' | 'all') {
  if (command === 'selected') {
    await handleExportSelected();
    return;
  }

  await handleExportAll();
}

async function handleSend(row: Api.Performance.Sheet.Sheet) {
  if (!row.fileId) {
    window.$message?.warning('请先保存绩效 Excel 后再发送');
    return;
  }

  const actionText = row.statusCode === 'rejected' ? '重新发送' : '发送';
  try {
    await ElMessageBox.confirm(`确认${actionText}${row.employeeName}的绩效表吗？`, `${actionText}确认`, {
      type: 'warning',
      confirmButtonText: `确认${actionText}`,
      cancelButtonText: '取消'
    });
  } catch {
    return;
  }

  rowActionLoadingKey.value = `send:${row.id}`;
  const result =
    row.statusCode === 'rejected' ? await resendPerformanceSheet(row.id) : await sendPerformanceSheet(row.id);
  rowActionLoadingKey.value = '';

  if (result.error) return;

  window.$message?.success(`绩效表已${actionText}`);
  await reloadAfterMutation();
}

async function handleDelete(row: Api.Performance.Sheet.Sheet) {
  try {
    await ElMessageBox.confirm(`确认删除${row.employeeName}的 ${row.periodMonth} 绩效表吗？`, '删除确认', {
      type: 'warning',
      confirmButtonText: '确认删除',
      cancelButtonText: '取消'
    });
  } catch {
    return;
  }

  rowActionLoadingKey.value = `delete:${row.id}`;
  const { error } = await deletePerformanceSheet(row.id);
  rowActionLoadingKey.value = '';

  if (error) return;

  window.$message?.success('绩效表已删除');
  await reloadAfterMutation();
}

async function reloadAfterMutation() {
  await reloadTable(searchParams.pageNo ?? 1);
  await loadTeamSummary();
}

async function refreshPageData(page = 1) {
  await reloadTable(page);
  await loadTeamSummary();
}

async function loadSubordinateTree() {
  if (!canUseTeamDashboard.value) return;

  subordinateTreeLoading.value = true;
  const { error, data: treeData } = await fetchGetMySubordinateTree();
  subordinateTreeLoading.value = false;

  subordinateTree.value = error || !treeData ? null : treeData;
  selectedSubordinateUserId.value = treeData?.userId || null;
}

async function loadTeamSummary() {
  if (!isRootSelected.value) {
    teamSummary.value = null;
    return;
  }

  teamSummaryLoading.value = true;
  const { error, data: summaryData } = await fetchTeamPerformanceSummary({
    periodMonthStart: formattedPeriodMonthStart.value,
    periodMonthEnd: formattedPeriodMonthEnd.value
  });
  teamSummaryLoading.value = false;

  teamSummary.value = error || !summaryData ? null : summaryData;
}

async function loadDeptOptions() {
  if (!currentDeptId.value) {
    currentDeptId.value = authStore.userInfo.deptId || '';
  }

  if (!currentDeptId.value) {
    const { error, data: profileDetail } = await fetchGetMyProfileDetail({ userId: authStore.userInfo.userId });
    if (!error && profileDetail?.deptId) {
      currentDeptId.value = profileDetail.deptId;
    }
  }

  if (!currentDeptId.value) {
    deptOptions.value = [];
    return;
  }

  const { error, data: deptList } = await fetchGetDeptSelfAndChildren(currentDeptId.value);

  if (error || !deptList) {
    deptOptions.value = [];
    return;
  }

  deptOptions.value = deptList.map(node => ({ label: node.name, value: String(node.id) }));
}

async function loadDirectSubordinateOptions() {
  const loginUserId = authStore.userInfo.userId;
  if (!loginUserId) {
    directSubordinateOptions.value = [];
    return;
  }

  const { error, data: userList } = await fetchGetDirectSubordinates(loginUserId);

  if (error || !userList) {
    directSubordinateOptions.value = [];
    return;
  }

  directSubordinateOptions.value = userList.map(item => ({
    label: item.deptName ? `${item.nickname}（${item.deptName}）` : item.nickname,
    value: item.id
  }));
}

async function loadStatusOptions() {
  const { error, data: statusDict } = await fetchPerformanceSheetStatusDict();

  if (error || !statusDict) {
    statusOptions.value = [];
    return;
  }

  statusOptions.value = getPerformanceStatusOptions(statusDict);
}

async function handleTeamViewModeChange(mode: TeamViewMode) {
  teamViewMode.value = mode;

  if (mode === 'team') {
    if (!subordinateTree.value) {
      await loadSubordinateTree();
    }
    if (!selectedSubordinateUserId.value) {
      selectedSubordinateUserId.value = subordinateTree.value?.userId || null;
    }
  }
}

watch(
  () => [teamViewMode.value, selectedSubordinateUserId.value] as const,
  async ([mode], [previousMode]) => {
    if (mode === 'self' && previousMode === 'self') {
      return;
    }

    await refreshPageData(1);
  }
);

watch(
  () => isTeamMode.value,
  () => {
    reloadColumns();
  }
);

watch(excelVisible, isVisible => {
  if (isVisible) return;

  currentRow.value = null;
});

onMounted(async () => {
  await Promise.all([loadDeptOptions(), loadDirectSubordinateOptions(), loadStatusOptions()]);

  if (canUseTeamDashboard.value) {
    await loadSubordinateTree();
  }
});
</script>

<template>
  <div class="my-performance-page">
    <TeamContextPanel
      v-if="canUseTeamDashboard"
      v-model:mode="teamViewMode"
      :loading="subordinateTreeLoading"
      :selected-label="selectedTeamLabel"
      :subordinate-count="subordinateTree?.subordinateCount || 0"
      @update:mode="handleTeamViewModeChange"
    >
      <PerformanceSummary
        v-if="isRootSelected"
        :period-month-start="formattedPeriodMonthStart"
        :period-month-end="formattedPeriodMonthEnd"
        :loading="teamSummaryLoading"
        :summary="teamSummary"
        @reminded="loadTeamSummary"
      />
    </TeamContextPanel>

    <div class="my-performance-page__content" :class="{ 'my-performance-page__content--team': isTeamMode }">
      <div v-if="canUseTeamDashboard && isTeamMode" class="my-performance-page__sidebar">
        <SubordinateSelector
          v-model:selected-user-id="selectedSubordinateUserId"
          :loading="subordinateTreeLoading"
          :data="subordinateTree"
        />
      </div>

      <div class="my-performance-page__main">
        <PerformanceSearch
          v-model:model="searchParams"
          :team-mode="isTeamMode"
          :subordinate-options="subordinateOptions"
          :dept-options="deptOptions"
          :status-options="statusOptions"
          @reset="resetSearchParams"
          @search="handleSearch"
        />

        <ElCard class="flex-1-hidden card-wrapper" body-class="business-table-card-body">
          <template #header>
            <div class="flex flex-wrap items-center justify-between gap-12px">
              <div class="flex items-center gap-10px">
                <p class="text-16px font-600">{{ isTeamMode ? '团队绩效' : '我的绩效' }}</p>
                <ElTag effect="plain">{{ totalCount }}</ElTag>
              </div>
              <TableHeaderOperation v-model:columns="columnChecks" :loading="loading" @refresh="reloadTable">
                <template #default>
                  <ElDropdown v-if="canExport" trigger="click" @command="handleExportCommand">
                    <ElButton plain :loading="exporting">
                      <template #icon>
                        <icon-mdi-download class="text-icon" />
                      </template>
                      导出
                    </ElButton>
                    <template #dropdown>
                      <ElDropdownMenu>
                        <ElDropdownItem command="selected" :disabled="exporting || !selectedRows.length">
                          导出选中
                        </ElDropdownItem>
                        <ElDropdownItem command="all" :disabled="exporting">导出全部</ElDropdownItem>
                      </ElDropdownMenu>
                    </template>
                  </ElDropdown>
                  <ElButton v-if="isTeamMode && canManageTemplate" plain @click="templateVisible = true">
                    <template #icon>
                      <icon-mdi-file-cog-outline class="text-icon" />
                    </template>
                    模板
                  </ElButton>
                  <ElButton v-if="isTeamMode && canCreate" plain type="primary" @click="openCreateExcel">
                    <template #icon>
                      <icon-ic-round-plus class="text-icon" />
                    </template>
                    新增
                  </ElButton>
                </template>
              </TableHeaderOperation>
            </div>
          </template>

          <div class="flex-1">
            <ElTable
              v-loading="loading"
              height="100%"
              border
              row-key="id"
              :data="data"
              @selection-change="handleSelectionChange"
            >
              <template v-for="col in columns" :key="String(col.prop)">
                <ElTableColumn v-bind="col" />
              </template>
            </ElTable>
          </div>

          <div class="mt-20px flex justify-end">
            <ElPagination
              v-if="mobilePagination.total"
              layout="total,prev,pager,next,sizes"
              v-bind="mobilePagination"
              @current-change="mobilePagination['current-change']"
              @size-change="mobilePagination['size-change']"
            />
          </div>
        </ElCard>
      </div>
    </div>

    <PerformanceTemplateDialog
      v-if="templateVisible"
      v-model:visible="templateVisible"
      @updated="reloadAfterMutation"
    />

    <PerformanceExcelEditorDrawer
      v-model:visible="excelVisible"
      :row-data="currentRow"
      :mode="excelMode"
      :subordinate-options="directSubordinateOptions"
      @saved="reloadAfterMutation"
      @saved-and-sent="reloadAfterMutation"
    />

    <PerformanceActionDialog
      v-model:visible="actionVisible"
      :row-data="currentRow"
      :action-type="actionType"
      @submitted="reloadAfterMutation"
    />

    <PerformanceRecordDialog v-model:visible="recordVisible" :row-data="currentRow" />
  </div>
</template>

<style scoped lang="scss">
.my-performance-page {
  display: flex;
  flex-direction: column;
  gap: 16px;
  height: 100%;
  overflow: hidden;
}

.my-performance-page__content {
  display: flex;
  flex: 1;
  flex-direction: column;
  gap: 16px;
  min-height: 0;
}

.my-performance-page__main {
  display: flex;
  flex: 1;
  flex-direction: column;
  gap: 16px;
  min-width: 0;
  min-height: 0;
}

@media (min-width: 1280px) {
  .my-performance-page__content--team {
    display: grid;
    grid-template-columns: 240px minmax(0, 1fr);
  }

  .my-performance-page__sidebar {
    min-height: 0;
  }
}
</style>
