/*
 * @Author: code4eat awesomedema@gmail.com
 * @Date: 2023-03-03 11:30:33
 * @LastEditors: code4eat awesomedema@gmail.com
 * @LastEditTime: 2025-09-22 09:52:16
 * @FilePath: /KC-MiddlePlatform/src/pages/platform/setting/pubDicTypeMana/index.tsx
 * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
 */

import { SearchOutlined } from '@ant-design/icons';

import { Modal, message, Table, Button, Popconfirm, Tabs } from 'antd';
import { useEffect, useRef, useState } from 'react';

import {
  calculateReq,
  cancelAllocation,
  cancelIncomeCollection,
  downloadTemplateReq,
  generateReportHandle,
  getAfterCostShareSearchTableData,
  getAfterIncomeCollectionTableData,
  getCalcPageTableData,
  getUserHasReports,
  startAllocation,
  startIncomeCollection,
} from './service';

import './style.less';
import moment from 'moment';
import 'moment/locale/zh-cn';
import locale from 'antd/es/date-picker/locale/zh_CN';
import KCIMPagecontainer from '@/components/KCIMPageContainer';
import { KCIMTable } from '@/components/KCIMTable';
import buildVirtualBody from '@/components/VirtualTableBody';

import { ActionType, ProColumns } from '@ant-design/pro-components';
import { formatMoneyNumber, formatToPercentage } from '@/utils/format';

import {
  afterCollectionSearch,
  afterCostShareSearch,
  beforeCollectionSearch,
  beforeCostShareSearch,
  chargeItemCostCalc,
  clinicalPathway,
  costShare,
  costShareReportTable,
  departmentCostCalculate,
  departmentOperatingReport,
  diseaseCostCalculation,
  DRG_DIPCostCalc,
  incomeCollection,
  medicalMaterialCostCalc,
  medicalOrderItem,
  patientCostCalc,
  projectShareParamsCalc,
  unitPersonnelCostCalc,
  wholeHospCostCalculate,
  wholeHospOperatingReport,
} from './columns';
import {
  afterCollectionSearchFilterConf,
  afterCostShareSearchFilterConf,
  beforeCollectionSearchFilterConf,
  beforeCostShareSearchFilterConf,
  chargeItemCostCalcFilterConf,
  clinicalPathwayFilterConf,
  departmentCostCalculateFilterConf,
  diseaseCostCalculationFilterConf,
  DRG_DIPCostCalcFilterConf,
  medicalMaterialCostCalcFilterConf,
  medicalOrderItemFilterConf,
  patientCostCalcFilterConf,
  PatientItemCalcFilterConf,
  patientStandItemCostCalcFilterConf,
  projectCostCalcFilterConf,
  projectShareParamsCalcFilterConf,
  standardItemCostCalcFilterConf,
  standItemShareCostCalcFilterConf,
  unitPersonnelCostCalcFilterConf,
} from './config';

import ProgressModal from '@/components/ProgressModal';

import ExportProgressModal from '@/pages/reportExport/report/ExportProgressModal';
import { exportCalcPageDataToExcel } from '@/utils/exporter';

import { useAccess, useParams } from '@umijs/max';
import { useModel } from '@umijs/max';
// import { getParamsDataBySysId } from '@/services/getDic';

import { getCalcPageStrategy } from './strategy';
import { getPagePermissions } from './usePageAccess';
import FilterBar from './FilterBar';
import { createPagedExporter } from './usePagedExporter';

const calTypeStr = `ITEM_COST_CALCULATE${new Date().getTime()}`;
const DEFAULT_FONT_COLOR = 'rgba(0, 0, 0, 0.85)';

function transformChildToChildren(data: any[]) {
  return data.map((item) => {
    let newItem = { ...item };

    // 如果有子项，将 'child' 属性改为 'children'
    if (newItem.child) {
      newItem.children = transformChildToChildren(newItem.child);
      delete newItem.child; // 删除原始的 'child' 属性
    }

    return newItem;
  });
}

const getNextUnexpandedKeys = (data: any[], expandedKeys: any[] = []) => {
  let keys: any[] = [];

  const traverse = (nodes: any) => {
    for (const node of nodes) {
      // 如果当前节点还没有展开，就把它加入 keys
      if (!expandedKeys.includes(node.id)) {
        keys.push(node.id);
      }

      // 如果当前节点已经展开，继续遍历子节点
      if (node.children && expandedKeys.includes(node.id)) {
        traverse(node.children);
      }
    }
  };

  traverse(data);

  return keys;
};

export default function calcPageTemplate() {
  const { initialState, setInitialState } = useModel('@@initialState');
  const [computeDate, set_computeDate] = useState<string>(
    initialState ? initialState.computeDate : '',
  );
  const [tableDataFilterParams, set_tableDataFilterParams] = useState<any>({
    computeDate,
  });
  // 已不使用，移除避免误导：tableDataSearchKeywords
  const tableRef = useRef<ActionType>();
  const [loading, set_loading] = useState(false);
  const params = useParams();
  const [columns, set_columns] = useState<ProColumns[]>([]);
  const [filterConf, set_filterConf] = useState<any[]>([]);
  const [scrollX, set_scrollX] = useState(500);
  const [ifShowCalcBtn, set_ifShowCalcBtn] = useState(true);
  const [ifShowExportBtn, set_ifShowExportBtn] = useState(false);
  const [totalCount, set_totalCount] = useState<undefined | number>(undefined);
  const [inputValues, setInputValues] = useState<{ [key: string]: any }>({});
  const [pagePermissions, set_pagePermissions] = useState<Set<string>>(
    new Set(),
  );
  const [tabs, set_tabs] = useState<any[]>([]);
  const [currentTabKey, set_currentTabKey] = useState<string | undefined>(
    undefined,
  );
  const [tableExtraProps, set_tableExtraProps] = useState<any>({});
  const [bottomSummaryRow, set_bottomSummaryRow] = useState<any | null>(null); // 专用于固定底部“总计”

  const access = useAccess();

  const [isModalVisible, setIsModalVisible] = useState(false);
  const [openProcessModal, set_openProcessModal] = useState(false);
  const [allParentsKeys, set_allParentsKeys] = useState<any[]>([]);
  const [
    hospitalServiceProjectExpandedKeys,
    set_hospitalServiceProjectExpandedKeys,
  ] = useState<any[]>([]);
  const [dataSource, set_dataSource] = useState<any[]>([]);
  const exporter = useRef(
    createPagedExporter<{ [k: string]: any }>({
      pageSize: 100,
      request: async (params) => {
        const resp: any = await getTableData(params);
        if (!resp) return { data: [], total: 0 } as any;
        const { total = 0, data = [] } = resp;
        return { data, total } as any;
      },
    }),
  );

  const getTableData = async (params: any) => {
    const { reportType } = params;
    if (params.calcPageKey == 'wholeHospCostCalculate' && !reportType) {
      return {
        data: [],
        success: false,
        total: 0,
        pageSize: 0,
        totalPage: 0,
      };
    }

    // 构造请求参数（可按需剔除仅前端检索的字段）
    let reqParams: any = { ...params };
    if (
      params.calcPageKey === 'deptDirectMedicalCost' &&
      'departmentName' in reqParams
    ) {
      // deptDirectMedicalCost 仅前端检索：不将 departmentName 传给后端
      const { departmentName, ...rest } = reqParams;
      reqParams = rest;
    }
    if (
      params.calcPageKey === 'deptFullDirectCost' &&
      'departmentName' in reqParams
    ) {
      // deptFullDirectCost 仅前端检索：不将 departmentName 传给后端
      const { departmentName, ...rest } = reqParams;
      reqParams = rest;
    }
    if (
      params.calcPageKey === 'clinicalDeptMedicalCost' &&
      'departmentName' in reqParams
    ) {
      // clinicalDeptMedicalCost 仅前端检索
      const { departmentName, ...rest } = reqParams;
      reqParams = rest;
    }
    if (
      params.calcPageKey === 'clinicalDeptFullCost' &&
      'departmentName' in reqParams
    ) {
      // clinicalDeptFullCost 仅前端检索
      const { departmentName, ...rest } = reqParams;
      reqParams = rest;
    }
    if (
      params.calcPageKey === 'hospitalDeptVisitCost' &&
      'departmentName' in reqParams
    ) {
      // hospitalDeptVisitCost 仅前端检索
      const { departmentName, ...rest } = reqParams;
      reqParams = rest;
    }
    if (
      params.calcPageKey === 'deptCostAllocationSummary' &&
      'departmentName' in reqParams
    ) {
      // deptCostAllocationSummary 仅前端检索
      const { departmentName, ...rest } = reqParams;
      reqParams = rest;
    }
    if (
      params.calcPageKey === 'hospitalDeptBedDayCost' &&
      'departmentName' in reqParams
    ) {
      // hospitalDeptBedDayCost 仅前端检索
      const { departmentName, ...rest } = reqParams;
      reqParams = rest;
    }
    // diseaseCostDetail 和 diseaseCostCompositionDetail 已改为后端分页+检索，diseaseFilter 参数传给后端
    if (
      params.calcPageKey === 'deptDiseaseCostCompositionDetail' &&
      'itemName' in reqParams
    ) {
      // 服务单元病种成本构成明细表：病种名称仅前端检索
      const { itemName, ...rest } = reqParams;
      reqParams = rest;
    }
    if (
      params.calcPageKey === 'medicalServiceCostDetail' &&
      'itemFilter' in reqParams
    ) {
      // medicalServiceCostDetail 仅前端检索：项目代码/名称
      const { itemFilter, ...rest } = reqParams as any;
      reqParams = rest;
    }

    const resp = await getCalcPageTableData({ ...reqParams });
    if (resp) {
      try {
        if (
          params.calcPageKey == 'projectShareParamsCalc' ||
          params.calcPageKey == 'projectCostCalc' ||
          params.calcPageKey == 'patientItemCalc' ||
          params.calcPageKey == 'standardItemCostCalc' ||
          params.calcPageKey == 'patientStandItemCostCalc' ||
          params.calcPageKey == 'standItemShareCostCalc'
        ) {
          const {
            pageData: { list = [], pageSize, totalCount, totalPage },
            title,
          } = resp;
          const columns: ProColumns[] = title.map(
            (item: any, index: number) => {
              return {
                title: item.name,
                dataIndex: `${item.code}`,
                key: `${item.code}`,
                // width: getStringWidth(item.name, '14px'),
                ellipsis: true,
                fixed: item.freeze ? true : false,
                hideInTable: item.hide,
                align: item.dataType == 3 ? 'right' : 'left',
                sorter: item.sortStatus
                  ? (a: any, b: any) => {
                      if (item.dataType == 3) {
                        //数值
                        return b[`${item.code}`] - a[`${item.code}`];
                      } else {
                        return b[`${item.code}`]?.localeCompare(
                          a[`${item.code}`],
                        );
                      }
                    }
                  : undefined,
              };
            },
          );
          set_columns([...columns]);

          const data = list.map((item: any, idx: number) => {
            let rowData: { [key: string]: any } = {};

            item.forEach((b: any) => {
              const needTitle = title.filter((a: any) => a.code == b.code);
              if (needTitle.length > 0) {
                rowData[`${needTitle[0].code}`] = b.value;
              }
            });
            // 生成稳定 id：按列顺序拼接当前行各列值
            const stableId = title
              .map((t: any) => String(rowData[t.code] ?? ''))
              .join('|');
            return {
              ...item,
              ...rowData,
              id: stableId || String(idx),
              columns,
            };
          });

          return {
            data: data,
            success: true,
            total: totalCount,
            pageSize: pageSize,
            totalPage: totalPage,
          };
        }
        // 新增：临床服务类科室全成本构成分析表（动态多级表头）
        if (params.calcPageKey === 'clinicalDeptFullCostAnalysis') {
          const { title = [], data: assignmentData = [] } = resp || {};

          // 递归生成多级列
          const buildColumns = (nodes: any[]): ProColumns[] => {
            return (nodes || []).map((node: any) => {
              const hasChildren =
                Array.isArray(node.child) && node.child.length > 0;
              const { isFixed } = node || {};
              const column: any = {
                title: node.responsibilityName,
                key: String(
                  node.responsibilityCode ||
                    node.responsibilityName ||
                    Math.random(),
                ),
              };
              if (hasChildren) {
                const childCols = buildColumns(node.child);
                column.children = childCols;
                // 若自身标记固定，或任何子列固定，则连同父级一起固定到右侧
                const childHasFixed = (childCols || []).some((c: any) =>
                  Boolean(c.fixed),
                );
                if (isFixed === 1 || childHasFixed) {
                  column.fixed = 'right';
                }
              } else {
                const { dataType, decimalPlace, permil } = node || {};
                column.dataIndex = String(node.responsibilityCode);
                column.align = 'right';
                column.width = 130;
                if (isFixed === 1) column.fixed = 'right';
                // 挂载元信息，便于导出时复用
                column.__meta = { dataType, decimalPlace, permil };
                column.renderText = (num: any) => {
                  if (dataType === 2) {
                    // 百分比显示
                    if (typeof num === 'number' && !isNaN(num)) {
                      const dp =
                        typeof decimalPlace === 'number' ? decimalPlace : 2;
                      return `${(num * 100).toFixed(dp)}%`;
                    }
                    return num;
                  }
                  const dp =
                    typeof decimalPlace === 'number' ? decimalPlace : 2;
                  const useThousand = permil === 1 || permil === true;
                  return formatMoneyNumber(num, {
                    decimalPlaces: dp,
                    useThousandSeparator: useThousand,
                  });
                };
              }
              return column;
            });
          };

          const columns: ProColumns[] = [
            {
              title: '项目名称',
              dataIndex: 'reportName',
              key: 'reportName',
              width: 240,
              fixed: 'left' as any,
            },
            ...buildColumns(title),
          ];
          set_columns(columns);

          // 动态计算 scrollX：按所有叶子列宽度求和
          const sumLeafWidths = (cols: any[]): number => {
            let sum = 0;
            const loop = (arr: any[]) => {
              (arr || []).forEach((c: any) => {
                if (c.children && c.children.length > 0) {
                  loop(c.children);
                } else {
                  sum += typeof c.width === 'number' ? c.width : 150;
                }
              });
            };
            loop(cols as any[]);
            return sum;
          };

          const dynamicScrollX = sumLeafWidths(columns as any[]) + 80; // 额外留白
          set_scrollX(dynamicScrollX);

          // 行数据：将 data 中的 code/value 映射为列
          const data = (assignmentData || []).map((row: any, idx: number) => {
            const rowData: any = { reportName: row.reportName };
            (row.data || []).forEach((cell: any) => {
              rowData[String(cell.code)] = cell.value;
            });
            return { id: String(idx), ...rowData };
          });

          // 返回表格数据
          return {
            data,
            success: true,
            total: Array.isArray(data) ? data.length : 0,
            pageSize: Array.isArray(data) ? data.length : 0,
            totalPage: 1,
          };
        }
        // 新增：服务单元病种成本构成明细表（动态多级表头+数据，后端分页+检索）
        if (params.calcPageKey === 'deptDiseaseCostCompositionDetail') {
          const {
            title = [],
            data: rowList = [],
            totalCount,
            pageSize,
            totalPage,
          } = resp || {};

          // 递归生成多级列（透传 dataType/decimalPlace/isFixed/permil，并挂载统一 renderText 与 __meta）
          const buildColumns = (nodes: any[]): ProColumns[] => {
            return (nodes || []).map((node: any) => {
              const hasChildren =
                Array.isArray(node.child) && node.child.length > 0;
              const column: any = {
                title: node.responsibilityName,
                key: String(
                  node.responsibilityCode ||
                    node.responsibilityName ||
                    Math.random(),
                ),
              };
              if (hasChildren) {
                column.children = buildColumns(node.child);
              } else {
                const { dataType, decimalPlace, permil, isFixed } = node || {};
                column.dataIndex = String(node.responsibilityCode);
                column.align = 'right';
                column.width = 130;
                if (isFixed === 1) column.fixed = 'right';
                column.__meta = { dataType, decimalPlace, permil };
                column.renderText = (num: any) => {
                  if (dataType === 2) {
                    // 百分比
                    if (typeof num === 'number' && !isNaN(num)) {
                      const dp =
                        typeof decimalPlace === 'number' ? decimalPlace : 2;
                      return `${(num * 100).toFixed(dp)}%`;
                    }
                    return num;
                  }
                  const dp =
                    typeof decimalPlace === 'number' ? decimalPlace : 2;
                  const useThousand = permil === 1 || permil === true;
                  return formatMoneyNumber(num, {
                    decimalPlaces: dp,
                    useThousandSeparator: useThousand,
                  });
                };
              }
              return column;
            });
          };

          const dynamicCols: ProColumns[] = [
            {
              title: '病种编码',
              dataIndex: 'reportCode',
              key: 'reportCode',
              width: 140,
              fixed: 'left' as any,
            },
            {
              title: '病种名称',
              dataIndex: 'reportName',
              key: 'reportName',
              width: 220,
              fixed: 'left' as any,
            },
            {
              title: '病种成本',
              dataIndex: 'totalValue',
              key: 'totalValue',
              width: 150,
              align: 'right',
              /* 该列也 fixed 左侧，三列一起固定 */ fixed: 'left' as any,
              renderText: (num: any) =>
                formatMoneyNumber(num, {
                  decimalPlaces: 2,
                  useThousandSeparator: true,
                }),
            } as any,
            ...buildColumns(title),
          ];
          set_columns(dynamicCols);

          const sumLeafWidths = (cols: any[]): number => {
            let sum = 0;
            const loop = (arr: any[]) => {
              (arr || []).forEach((c: any) => {
                if (c.children && c.children.length > 0) {
                  loop(c.children);
                } else {
                  sum += typeof c.width === 'number' ? c.width : 150;
                }
              });
            };
            loop(cols as any[]);
            return sum;
          };
          const baseWidth = 140 + 220 + 150;
          const dynamicScrollX =
            sumLeafWidths(dynamicCols.slice(3) as any[]) + baseWidth + 80;
          set_scrollX(dynamicScrollX);

          const rows = Array.isArray(rowList) ? rowList : [];
          const data = rows.map((row: any, idx: number) => {
            const rowData: any = {
              reportCode: row.reportCode,
              reportName: row.reportName,
              totalValue: row.totalValue,
            };
            ((row?.data || []) as any[]).forEach((cell: any) => {
              rowData[String(cell.code)] = cell.value;
            });
            return { id: String(idx), ...rowData };
          });

          return {
            data,
            success: true,
            total:
              typeof totalCount === 'number'
                ? totalCount
                : Array.isArray(data)
                ? data.length
                : 0,
            pageSize:
              typeof pageSize === 'number'
                ? pageSize
                : Array.isArray(data)
                ? data.length
                : 0,
            totalPage: typeof totalPage === 'number' ? totalPage : 1,
          };
        }
        // 新增：医院服务单元DRG成本构成明细表（动态多级表头+数据）
        if (params.calcPageKey === 'deptDrgCostCompositionDetail') {
          const { title = [], data: rowList = [] } = resp || {};

          // 本地检索：按 DRG 名称（reportName）过滤
          let filteredRows = Array.isArray(rowList) ? rowList : [];
          try {
            const kw = String((params as any).itemName || '').trim();
            if (kw) {
              filteredRows = filteredRows.filter((row: any) =>
                String(row?.reportName || '').includes(kw),
              );
            }
          } catch {}

          const buildColumns = (nodes: any[]): ProColumns[] => {
            return (nodes || []).map((node: any) => {
              const hasChildren =
                Array.isArray(node.child) && node.child.length > 0;
              const column: any = {
                title: node.responsibilityName,
                key: String(
                  node.responsibilityCode ||
                    node.responsibilityName ||
                    Math.random(),
                ),
              };
              if (hasChildren) {
                column.children = buildColumns(node.child);
              } else {
                const { dataType, decimalPlace, permil, isFixed } = node || {};
                column.dataIndex = String(node.responsibilityCode);
                column.align = 'right';
                column.width = 130;
                if (isFixed === 1) column.fixed = 'right';
                column.__meta = { dataType, decimalPlace, permil };
                column.renderText = (num: any) => {
                  if (dataType === 2) {
                    if (typeof num === 'number' && !isNaN(num)) {
                      const dp =
                        typeof decimalPlace === 'number' ? decimalPlace : 2;
                      return `${(num * 100).toFixed(dp)}%`;
                    }
                    return num;
                  }
                  const dp =
                    typeof decimalPlace === 'number' ? decimalPlace : 2;
                  const useThousand = permil === 1 || permil === true;
                  return formatMoneyNumber(num, {
                    decimalPlaces: dp,
                    useThousandSeparator: useThousand,
                  });
                };
              }
              return column;
            });
          };

          const dynamicCols: ProColumns[] = [
            {
              title: 'DRG编码',
              dataIndex: 'reportCode',
              key: 'reportCode',
              width: 140,
              fixed: 'left' as any,
            },
            {
              title: 'DRG名称',
              dataIndex: 'reportName',
              key: 'reportName',
              width: 320,
              fixed: 'left' as any,
            },
            {
              title: 'DRG成本',
              dataIndex: 'totalValue',
              key: 'totalValue',
              width: 150,
              align: 'right',
              renderText: (num: any) =>
                formatMoneyNumber(num, {
                  decimalPlaces: 2,
                  useThousandSeparator: true,
                }),
            } as any,
            ...buildColumns(title),
          ];
          set_columns(dynamicCols);

          const sumLeafWidths = (cols: any[]): number => {
            let sum = 0;
            const loop = (arr: any[]) => {
              (arr || []).forEach((c: any) => {
                if (c.children && c.children.length > 0) {
                  loop(c.children);
                } else {
                  sum += typeof c.width === 'number' ? c.width : 150;
                }
              });
            };
            loop(cols as any[]);
            return sum;
          };
          const baseWidth = 140 + 320 + 150;
          const dynamicScrollX =
            sumLeafWidths(dynamicCols.slice(3) as any[]) + baseWidth + 80;
          set_scrollX(dynamicScrollX);

          const data = (filteredRows || []).map((row: any, idx: number) => {
            const rowData: any = {
              reportCode: row.reportCode,
              reportName: row.reportName,
              totalValue: row.totalValue,
            };
            ((row?.data || []) as any[]).forEach((cell: any) => {
              rowData[String(cell.code)] = cell.value;
            });
            return { id: String(idx), ...rowData };
          });

          return {
            data,
            success: true,
            total: Array.isArray(data) ? data.length : 0,
            pageSize: Array.isArray(data) ? data.length : 0,
            totalPage: 1,
          };
        }
        // 兼容多种返回结构：list / data / 直接数组
        let data =
          resp.list && resp.list != null
            ? resp.list
            : Array.isArray(resp)
            ? resp
            : Array.isArray(resp?.data)
            ? resp.data
            : [];
        if (params.calcPageKey == 'unitPersonnelCostCalc') {
          data = data
            ? data.map((a: any) => ({ ...a, children: a.childList }))
            : [];
        }
        if (params.calcPageKey == 'wholeHospCostCalculate') {
          data = data ? transformChildToChildren(data) : [];
          set_dataSource(data);
        }
        // deptDirectMedicalCost / deptCostAllocationSummary：将“总计”行剥离，改由 summary 固定到底部展示
        if (
          params.calcPageKey === 'deptDirectMedicalCost' ||
          params.calcPageKey === 'deptCostAllocationSummary'
        ) {
          const totalIdx = Array.isArray(data)
            ? data.findIndex((row: any) =>
                String(row?.responsibilityName || '').includes('总计'),
              )
            : -1;
          if (totalIdx > -1) {
            try {
              set_bottomSummaryRow(data[totalIdx]);
            } catch {}
            data = [...data.slice(0, totalIdx), ...data.slice(totalIdx + 1)];
          } else {
            set_bottomSummaryRow(null);
          }
        }
        if (params.calcPageKey === 'deptFullDirectCost') {
          set_bottomSummaryRow(null);
        }
        if (params.calcPageKey === 'clinicalDeptMedicalCost') {
          set_bottomSummaryRow(null);
        }
        if (params.calcPageKey === 'clinicalDeptFullCost') {
          set_bottomSummaryRow(null);
        }
        if (
          params.calcPageKey == 'beforeCollectionSearch' ||
          params.calcPageKey == 'beforeCostShareSearch' ||
          params.calcPageKey == 'afterCostShareSearch' ||
          params.calcPageKey == 'afterCollectionSearch'
        ) {
          const { totalAmount = 0 } = resp;
          set_totalCount(totalAmount);
        } else {
          set_totalCount(undefined);
        }

        // 前端检索：deptDirectMedicalCost / deptCostAllocationSummary 按科室名称本地过滤
        if (
          (params.calcPageKey === 'deptDirectMedicalCost' ||
            params.calcPageKey === 'deptCostAllocationSummary') &&
          params.departmentName
        ) {
          const kw = String(params.departmentName || '').trim();
          if (kw) {
            data = data.filter((row: any) =>
              String(row.responsibilityName || '').includes(kw),
            );
          }
        }
        // 前端检索：deptFullDirectCost 按科室名称本地过滤
        if (
          params.calcPageKey === 'deptFullDirectCost' &&
          params.departmentName
        ) {
          const kw = String(params.departmentName || '').trim();
          if (kw) {
            data = data.filter((row: any) =>
              String(row.responsibilityName || '').includes(kw),
            );
          }
        }
        if (
          params.calcPageKey === 'clinicalDeptMedicalCost' &&
          params.departmentName
        ) {
          const kw = String(params.departmentName || '').trim();
          if (kw) {
            data = data.filter((row: any) =>
              String(row.responsibilityName || '').includes(kw),
            );
          }
        }
        if (
          params.calcPageKey === 'clinicalDeptFullCost' &&
          params.departmentName
        ) {
          const kw = String(params.departmentName || '').trim();
          if (kw) {
            data = data.filter((row: any) =>
              String(row.responsibilityName || '').includes(kw),
            );
          }
        }
        if (
          params.calcPageKey === 'hospitalDeptVisitCost' &&
          params.departmentName
        ) {
          const kw = String(params.departmentName || '').trim();
          if (kw) {
            data = data.filter((row: any) =>
              String(row.responsibilityName || '').includes(kw),
            );
          }
        }
        if (
          params.calcPageKey === 'hospitalDeptBedDayCost' &&
          params.departmentName
        ) {
          const kw = String(params.departmentName || '').trim();
          if (kw) {
            data = data.filter((row: any) =>
              String(row.responsibilityName || '').includes(kw),
            );
          }
        }
        // diseaseCostDetail 和 diseaseCostCompositionDetail 已改为后端检索，不再前端过滤
        // 前端检索：drgCostDetail / drgCostCompositionDetail / deptDrgCostCompositionDetail 按 DRG 名称本地过滤
        if (
          (params.calcPageKey === 'drgCostDetail' ||
            params.calcPageKey === 'drgCostCompositionDetail' ||
            params.calcPageKey === 'deptDrgCostCompositionDetail') &&
          params.itemName
        ) {
          const kw = String(params.itemName || '').trim();
          if (kw) {
            data = data.filter((row: any) =>
              String(row.itemName || '').includes(kw),
            );
          }
        }
        // 前端检索：deptDiseaseCostCompositionDetail 按病种名称本地过滤
        if (
          params.calcPageKey === 'deptDiseaseCostCompositionDetail' &&
          params.itemName
        ) {
          const kw = String(params.itemName || '').trim();
          if (kw) {
            data = data.filter((row: any) =>
              String(row.reportName || '').includes(kw),
            );
          }
        }
        // 前端检索：hospitalServiceProjectCost 按项目名称本地过滤（树结构兼容）
        if (
          params.calcPageKey === 'hospitalServiceProjectCost' &&
          params.itemName
        ) {
          const kw = String(params.itemName || '').trim();
          if (kw) {
            const filterTreeByItemName = (nodes: any[]): any[] => {
              if (!Array.isArray(nodes)) return [];
              const results: any[] = [];
              for (const node of nodes) {
                const name = String(node?.itemName || '');
                const rawChildren = (
                  Array.isArray(node?.children)
                    ? node.children
                    : Array.isArray(node?.child)
                    ? node.child
                    : []
                ) as any[];
                const filteredChildren = filterTreeByItemName(rawChildren);
                const selfMatch = name.includes(kw);
                if (selfMatch || filteredChildren.length > 0) {
                  const copy: any = { ...node };
                  if (Array.isArray(node?.children))
                    copy.children = filteredChildren;
                  else if (Array.isArray(node?.child))
                    copy.child = filteredChildren;
                  else if (filteredChildren.length > 0)
                    copy.children = filteredChildren;
                  results.push(copy);
                }
              }
              return results;
            };
            data = filterTreeByItemName(data);
          }
        }

        // 规范化 hospitalServiceProjectCost 的树数据：统一 children，并生成稳定唯一的 id，避免展开联动
        if (params.calcPageKey === 'hospitalServiceProjectCost') {
          const normalizeTree = (
            nodes: any[],
            parentKey: string = '',
          ): any[] => {
            if (!Array.isArray(nodes)) return [];
            return nodes.map((node: any, idx: number) => {
              const copy: any = { ...node };
              const rawChildren = Array.isArray(copy.children)
                ? copy.children
                : Array.isArray(copy.child)
                ? copy.child
                : [];
              const id = `${parentKey}${parentKey ? '-' : ''}${idx}`;
              copy.id = id;
              if (rawChildren && rawChildren.length > 0) {
                copy.children = normalizeTree(rawChildren, id);
              } else {
                // 无子节点时去除空 children，避免渲染干扰
                if (
                  copy.children &&
                  Array.isArray(copy.children) &&
                  copy.children.length === 0
                ) {
                  delete copy.children;
                }
              }
              // 统一去掉 child
              if (copy.child) delete copy.child;
              return copy;
            });
          };
          data = normalizeTree(data);
        }
        // 前端检索：medicalServiceCostDetail 按项目代码或名称本地过滤
        if (
          params.calcPageKey === 'medicalServiceCostDetail' &&
          params.itemFilter
        ) {
          const kw = String(params.itemFilter || '').trim();
          if (kw) {
            const includesKw = (v: any) => String(v || '').includes(kw);
            data = data.filter(
              (row: any) =>
                includesKw(row.itemCode) || includesKw(row.itemName),
            );
          }
        }

        // 非分页接口兜底处理：total 取数据条数
        const totalCountFallback =
          typeof resp?.totalCount === 'number' && !isNaN(resp.totalCount)
            ? resp.totalCount
            : Array.isArray(data)
            ? data.length
            : 0;
        return {
          data,
          success: true,
          total: totalCountFallback,
          pageSize: resp.pageSize || totalCountFallback,
          totalPage: resp.totalPage || 1,
        };
      } catch (err) {
        console.log({ err });
      }
    }
    return { data: [], success: false, total: 0, pageSize: 0, totalPage: 0 };
  };

  const tableDataSearchHandle = (paramName: string) => {
    set_tableDataFilterParams((prev: any) => ({
      ...prev,
      [`${paramName}`]: inputValues[`${paramName}`],
    }));
  };

  const calcFunc = () => {
    Modal.confirm({
      title: '注意',
      content: '计算操作会覆盖当月已计算的数据，是否继续操作？',
      okText: '确定',
      cancelText: '取消',
      onOk: async (...args) => {
        if (
          params.calcPageKey != 'chargeItemCostCalc' &&
          params.calcPageKey != 'wholeHospCostCalculate'
        ) {
          set_loading(true);
          const resp = await calculateReq(computeDate, params.calcPageKey);
          if (resp) {
            set_loading(false);
            message.success('操作成功！');
            tableRef.current?.reload();
          } else {
            set_loading(false);
          }
        }

        if (params.calcPageKey == 'chargeItemCostCalc') {
          startChargeItemCalculateWithProgress();
          return false;
        }
        if (params.calcPageKey == 'wholeHospCostCalculate') {
          const resp = await calculateReq(
            computeDate,
            params.calcPageKey,
            currentTabKey,
          );
          if (resp) {
            set_loading(false);
            message.success('操作成功！');
            tableRef.current?.reload();
          } else {
            set_loading(false);
          }
          return false;
        }
      },
    });
  };

  const startChargeItemCalculateWithProgress = async () => {
    try {
      setIsModalVisible(true);
      const resp = await calculateReq(
        computeDate,
        params.calcPageKey,
        calTypeStr,
      );
      setIsModalVisible(false);
      tableRef.current?.reload();
      if (!resp) {
        message.error('计算失败');
      }
    } catch (err) {
      setIsModalVisible(false);
      message.error('计算失败');
    }
  };

  // 旧的内联筛选项生成已由 FilterBar 替代

  const optionBtnGroupshandle = async (isCollection: boolean, record: any) => {
    if (params.calcPageKey == 'incomeCollection') {
      const { year, month } = record;
      if (isCollection) {
        const resp = await cancelIncomeCollection({ year, month });
        if (resp) {
          message.success('操作成功！');
          tableRef.current?.reload();
        }
      } else {
        Modal.confirm({
          title: '注意',
          content: '收入归集操作会覆盖已有的归集后数据，确定要继续操作？',
          okText: '确定',
          cancelText: '取消',
          onOk: async (...args) => {
            set_loading(true);
            const resp = await startIncomeCollection({ year, month });
            if (resp) {
              set_loading(false);
              message.success('操作成功！');
              tableRef?.current?.reload();
            } else {
              set_loading(false);
            }
          },
        });
      }
    }
    if (params.calcPageKey == 'costShare') {
      const { year, month } = record;
      if (!isCollection) {
        //开始分摊
        Modal.confirm({
          title: '注意',
          content: '成本分摊操作会覆盖已有的分摊后数据，确定要继续操作？',
          okText: '确定',
          cancelText: '取消',
          onOk: async (...args) => {
            set_loading(true);
            const resp = await startAllocation({ year, month });
            if (resp) {
              set_loading(false);
              message.success('操作成功！');
              tableRef?.current?.reload();
            } else {
              set_loading(false);
            }
          },
        });
      }
      if (isCollection) {
        //撤销分摊
        const resp = await cancelAllocation({ year, month });
        if (resp) message.success('操作成功！');
        tableRef?.current?.reload();
      }
    }
  };

  const openDataTable = async () => {
    set_loading(true);
    try {
      const { responsibilityCode = null } = tableDataFilterParams;
      let resp: any = undefined;
      if (params.calcPageKey == 'afterCostShareSearch') {
        resp = await getAfterCostShareSearchTableData({
          year: `${computeDate}-01`,
          responsibilityCode,
        });
      }
      if (params.calcPageKey == 'afterCollectionSearch') {
        resp = await getAfterIncomeCollectionTableData({
          ...params,
          date: `${computeDate.replace(/-/g, '')}`,
        });
      }

      if (resp) {
        const { titleMap = {}, realData = [], totalMap = {} } = resp;
        const titleMapToArr = Object.entries(titleMap);
        const totalMapToArr = Object.entries(totalMap);
        const columns = [...titleMapToArr].map((item, index) => {
          if (index == 0 || index == [...titleMapToArr].length - 1) {
            return {
              title: item[1],
              key: item[0],
              dataIndex: item[0],
              fixed: index == 0 ? 'left' : 'right',
              width: 150,
            };
          }
          return {
            title: item[1],
            dataIndex: item[0],
            key: item[0],
            width: 150,
          };
        });
        set_loading(false);
        Modal.info({
          title: '报表数据',
          icon: '',
          okText: '确定',
          width: 800,
          content: (
            <KCIMTable
              rowKey="id"
              scroll={{ x: columns.length * 150, y: 450 }}
              columns={columns as ProColumns[]}
              dataSource={[...realData]}
              pagination={false}
              summary={() => (
                <Table.Summary fixed>
                  <Table.Summary.Row className="rowCell">
                    {/* <Table.Summary.Cell className="firstCell" index={0}>合计</Table.Summary.Cell> */}
                    {totalMapToArr.map((item, index) => {
                      return (
                        <Table.Summary.Cell
                          key={index}
                          className={
                            index == totalMapToArr.length - 1
                              ? 'ant-table-cell ant-table-cell-fix-right ant-table-cell-fix-right-last'
                              : 'cell'
                          }
                          index={index}
                        >
                          {item[1] as any}
                        </Table.Summary.Cell>
                      );
                    })}
                  </Table.Summary.Row>
                </Table.Summary>
              )}
            />
          ),
        });
      }
    } catch (err) {
      message.error('获取报表数据失败');
      console.error(err);
    }
  };

  const generateReport = async () => {
    // {date:computeDate,reportType:0}
    if (params.calcPageKey == 'departmentOperatingReport') {
      const resp = await generateReportHandle(
        { date: `${computeDate}-01`, reportType: 0 },
        '/costAccount/costdepartmentprofit/getDepartProfitReport',
      );
      if (resp) {
        tableRef.current?.reload();
      }
    }
    if (params.calcPageKey == 'wholeHospOperatingReport') {
      const resp = await generateReportHandle(
        { date: `${computeDate}-01`, reportType: 0 },
        '/costAccount/hospProfitAndLoss/report',
      );
      if (resp) {
        tableRef.current?.reload();
      }
    }
    if (params.calcPageKey == 'costShareReportTable') {
      const resp = await generateReportHandle(
        { date: `${computeDate}-01`, reportType: 0 },
        '/costAccount/hospProfitAndLoss/report',
      );
      if (resp) {
        tableRef.current?.reload();
      }
    }
  };

  const handleCompletion = () => {
    setIsModalVisible(false);
  };

  const handleExportCompletion = () => {
    set_openProcessModal(false);
    exportHandle(
      params.calcPageKey == 'wholeHospCostCalculate' ? 'reportName' : undefined,
    );
  };

  const exportHandle = (indentColumn?: string) => {
    // 将 indentColumn 设置为可选参数
    try {
      const rows = exporter.current.getAll();
      exportCalcPageDataToExcel(columns as any[], rows, {
        calcPageKey: params.calcPageKey,
        indentColumn,
      });
    } catch (err) {
      message.error('导出失败');
    } finally {
      exporter.current.reset();
    }
  };

  const fetchExportData = async () => {
    const { currentCount, totalCount } = await exporter.current.fetchData({
      ...tableDataFilterParams,
    } as any);
    return { currentCount, totalCount };
  };

  const handleExpandNext = () => {
    // 当前所有未展开的节点，第一层优先展开
    const keysToExpand = getNextUnexpandedKeys(dataSource, allParentsKeys);
    set_allParentsKeys((prev) =>
      Array.from(new Set([...prev, ...keysToExpand])),
    );
  };

  const handleCollapseAll = () => {
    set_allParentsKeys([]);
  };

  // 占比列显隐已迁入策略 onMount 处理

  const getTabs = async () => {
    const resp = await getUserHasReports();
    if (resp) {
      const { dataVoList } = resp;
      const filterArr = dataVoList.filter((a: any) => a.value == '2');
      set_tabs(
        filterArr.map((a: any) => ({
          label: a.name,
          value: a.code,
          key: a.code,
        })),
      );
      filterArr.length > 0 && set_currentTabKey(filterArr[0].code);
    }
  };

  useEffect(() => {
    setInputValues({});
    const { calcPageKey } = params;

    // 优先尝试通过策略注册表处理（最小接入，不影响原有分支作为兜底）
    const strategy = getCalcPageStrategy(calcPageKey);
    // 计算页面权限集合（同步计算，直接使用 perms 避免 state 异步问题）
    let perms = new Set<string>();
    try {
      perms = getPagePermissions(
        access,
        location.pathname.replace('/CostAccountingSys', ''),
      );
      set_pagePermissions(perms);
    } catch {}
    if (strategy) {
      const baseColumns = strategy.buildColumns();
      const enhanced = strategy.enhanceColumns
        ? strategy.enhanceColumns(baseColumns as any, {
            onIncomeAction: optionBtnGroupshandle,
            onShareAction: optionBtnGroupshandle,
            Popconfirm,
            downloadTemplateReq,
          })
        : baseColumns;
      set_columns(enhanced as any);
      set_filterConf(strategy.filterConf);
      // 结合策略按钮解析（直接使用刚计算的 perms，而不是 state）
      let showCalc = strategy.showCalcButton;
      let showExport = false;
      if (typeof strategy.resolveButtons === 'function') {
        const btns = strategy.resolveButtons({ pagePermissions: perms });
        if (typeof btns?.calculate === 'boolean') showCalc = btns.calculate;
        if (typeof btns?.export === 'boolean') showExport = btns.export;
      }
      set_ifShowCalcBtn(showCalc);
      set_ifShowExportBtn(showExport);
      set_scrollX(strategy.scrollX);
      // 让策略在装载期可调整列等
      if (typeof strategy.onMount === 'function') {
        strategy.onMount({ columns: enhanced, setColumns: set_columns });
      }
      // 让策略可配置表格额外属性（如禁用分页等）
      try {
        const extra =
          typeof strategy.tablePropsBuilder === 'function'
            ? strategy.tablePropsBuilder({ pagePermissions: perms })
            : undefined;
        set_tableExtraProps(extra || {});
      } catch {
        set_tableExtraProps({});
      }
    }
    // 命中策略且属于简单场景时，直接返回，避免进入后续冗长分支
    const simpleKeys = new Set([
      'unitPersonnelCostCalc',
      'patientCostCalc',
      'medicalMaterialCostCalc',
      'chargeItemCostCalc',
      'diseaseCostCalculation',
      'DRG_DIPCostCalc',
      'clinicalPathway',
      'medicalOrderItem',
      'beforeCollectionSearch',
      'afterCollectionSearch',
      'beforeCostShareSearch',
      'afterCostShareSearch',
      'projectShareParamsCalc',
      'standardItemCostCalc',
      'patientStandItemCostCalc',
      'standItemShareCostCalc',
      'patientItemCalc',
      'departmentCostCalculate',
      'costShareReportTable',
      'departmentOperatingReport',
      'wholeHospOperatingReport',
      'incomeCollection',
      'costShare',
      'projectCostCalc',
    ]);
    if (strategy && simpleKeys.has(calcPageKey as any)) {
      // 切换页面时重置筛选参数，避免携带上个页面的残留检索项
      set_tableDataFilterParams({ computeDate, calcPageKey });
      return;
    }
    // 其他场景均已由策略处理，无需在此分支初始化

    if (currentTabKey && params.calcPageKey == 'wholeHospCostCalculate') {
      set_tableDataFilterParams({
        computeDate,
        calcPageKey,
        reportType: currentTabKey,
      } as any);
    } else {
      set_tableDataFilterParams({ computeDate, calcPageKey } as any);
    }
  }, [params, currentTabKey]);

  useEffect(() => {
    if (params.calcPageKey == 'wholeHospCostCalculate') {
      getTabs();
    }
  }, [params]);

  return (
    <KCIMPagecontainer
      className="calcPageTemplate"
      title={false}
      style={
        params.calcPageKey == 'wholeHospCostCalculate' ? { paddingTop: 0 } : {}
      }
    >
      <ProgressModal
        title="计算进度"
        type={calTypeStr}
        onComplete={handleCompletion}
        visible={isModalVisible}
      />
      <ExportProgressModal
        visible={openProcessModal}
        onCancel={() => set_openProcessModal(false)}
        fetchData={fetchExportData}
        onCompletion={handleExportCompletion}
      />
      {params.calcPageKey == 'wholeHospCostCalculate' && (
        <Tabs
          defaultActiveKey={currentTabKey}
          items={tabs}
          key={'key'}
          onChange={(key) => set_currentTabKey(key)}
        />
      )}

      <div className="toolBar">
        <div className="filter">
          <FilterBar
            computeDate={computeDate}
            onDateChange={(dateString) => {
              set_computeDate(dateString);
              setInitialState((s: any) => ({ ...s, computeDate: dateString }));
              set_tableDataFilterParams((prev: any) => ({
                ...prev,
                computeDate: dateString,
              }));
            }}
            filterConf={filterConf as any}
            inputValues={inputValues}
            onInputChange={(key, value) =>
              setInputValues((prev) => ({ ...prev, [key]: value }))
            }
            onInputSearch={(key, value) =>
              set_tableDataFilterParams((prev: any) => ({
                ...prev,
                [key]: value,
              }))
            }
            onSelectChange={(key, value) =>
              set_tableDataFilterParams((prev: any) => ({
                ...prev,
                [key]: value,
              }))
            }
            onCascaderChange={(key, value) =>
              set_tableDataFilterParams((prev: any) => ({
                ...prev,
                [key]: value ? value[value.length - 1] : null,
              }))
            }
          />
        </div>
        <div className="btnGroup">
          {params.calcPageKey == 'wholeHospCostCalculate' && (
            <>
              <span className="btn" onClick={() => handleCollapseAll()}>
                全部折叠
              </span>
              <span
                className="btn"
                style={{ marginRight: 16 }}
                onClick={() => handleExpandNext()}
              >
                展开下一层
              </span>
            </>
          )}
          {(params.calcPageKey == 'deptDirectMedicalCost' ||
            params.calcPageKey == 'deptFullDirectCost' ||
            params.calcPageKey == 'clinicalDeptMedicalCost' ||
            params.calcPageKey == 'clinicalDeptFullCost' ||
            params.calcPageKey == 'clinicalDeptFullCostAnalysis' ||
            params.calcPageKey == 'deptCostAllocationSummary' ||
            params.calcPageKey == 'hospitalVisitCostComposition' ||
            params.calcPageKey == 'hospitalDeptVisitCost' ||
            params.calcPageKey == 'hospitalBedDayCostComposition' ||
            params.calcPageKey == 'hospitalDeptBedDayCost' ||
            params.calcPageKey == 'hospitalServiceProjectCost' ||
            params.calcPageKey == 'medicalServiceCostDetail' ||
            params.calcPageKey == 'diseaseCostDetail' ||
            params.calcPageKey == 'diseaseCostCompositionDetail' ||
            params.calcPageKey == 'deptDiseaseCostCompositionDetail' ||
            params.calcPageKey == 'drgCostDetail' ||
            params.calcPageKey == 'drgCostCompositionDetail' ||
            params.calcPageKey == 'deptDrgCostCompositionDetail' ||
            (params.calcPageKey == 'projectCostCalc' && ifShowExportBtn) ||
            (params.calcPageKey == 'wholeHospCostCalculate' &&
              pagePermissions.has('export'))) && (
            <a className="export" onClick={() => set_openProcessModal(true)}>
              导出
            </a>
          )}
          {(params.calcPageKey == 'wholeHospCostCalculate' ||
            ifShowCalcBtn) && (
            <a className="calc" onClick={() => calcFunc()}>
              计算
            </a>
          )}
          {(params.calcPageKey == 'afterCostShareSearch' ||
            params.calcPageKey == 'afterCollectionSearch') && (
            <Button
              loading={loading}
              size="small"
              className="reportDataBtn"
              onClick={() => openDataTable()}
            >
              报表数据
            </Button>
          )}
          {(params.calcPageKey == 'departmentOperatingReport' ||
            params.calcPageKey == 'wholeHospOperatingReport') && (
            <span className="reportDataBtn" onClick={() => generateReport()}>
              生成报表
            </span>
          )}
        </div>
      </div>

      <div style={{ marginTop: 16 }}>
        {(() => {
          const extraScroll = (tableExtraProps as any)?.scroll;
          const { scroll: _omitScroll, ...restTableProps } = (tableExtraProps ||
            {}) as any;
          const mergedY =
            extraScroll?.y ??
            (params.calcPageKey == 'afterCostShareSearch'
              ? `calc(100vh - 270px)`
              : `calc(100vh - 233px)`);

          // 在大表启用行虚拟化（不分页）：deptDiseaseCostCompositionDetail
          // diseaseCostDetail 和 diseaseCostCompositionDetail 已改为后端分页，不再使用行虚拟化
          const enableVirtual =
            params.calcPageKey === 'deptDiseaseCostCompositionDetail' &&
            typeof scrollX === 'number' &&
            typeof mergedY === 'number' &&
            Array.isArray(columns) &&
            columns.length > 0 &&
            // 若存在固定列，则关闭行虚拟化以保留 fixed 效果
            !(columns as any[])?.some?.((c: any) => Boolean(c?.fixed));

          const virtualComponents = enableVirtual
            ? {
                body: buildVirtualBody({
                  columns: columns as any,
                  height: mergedY as number,
                  width: scrollX as number,
                  rowHeight: 44,
                }),
              }
            : undefined;
          const renderColumns = enableVirtual
            ? (columns as any[]).map((c) => ({ ...c, fixed: undefined }))
            : columns;
          return (
            <KCIMTable
              columns={renderColumns}
              actionRef={tableRef}
              rowKey="id"
              components={virtualComponents as any}
              expandable={
                params.calcPageKey == 'wholeHospCostCalculate'
                  ? {
                      defaultExpandAllRows: true,
                      expandedRowKeys: allParentsKeys,
                      onExpand(expanded, record) {
                        const { id } = record;
                        if (!expanded) {
                          const expandedKeys = allParentsKeys.filter(
                            (a) => a != id,
                          );
                          set_allParentsKeys([...expandedKeys]);
                        } else {
                          set_allParentsKeys([...allParentsKeys, id]);
                        }
                      },
                    }
                  : params.calcPageKey == 'hospitalServiceProjectCost'
                  ? {
                      expandedRowKeys: hospitalServiceProjectExpandedKeys,
                      onExpand(expanded, record) {
                        const { id } = record;
                        if (!expanded) {
                          const expandedKeys =
                            hospitalServiceProjectExpandedKeys.filter(
                              (a) => a != id,
                            );
                          set_hospitalServiceProjectExpandedKeys([
                            ...expandedKeys,
                          ]);
                        } else {
                          set_hospitalServiceProjectExpandedKeys([
                            ...hospitalServiceProjectExpandedKeys,
                            id,
                          ]);
                        }
                      },
                    }
                  : undefined
              }
              rowClassName={(record) => {
                // 全院损益树表的行 class
                if (params.calcPageKey == 'wholeHospCostCalculate') {
                  return `${
                    record.children ? 'has-children ' : ''
                  }hover-row report-font-color-row`;
                }
                // 医院科室直接成本表/成本分摊汇总表：小计行高亮
                if (
                  params.calcPageKey == 'deptDirectMedicalCost' ||
                  params.calcPageKey == 'deptCostAllocationSummary'
                ) {
                  const name = String(record.responsibilityName || '');
                  return name.includes('小计') ? 'subtotal-row' : '';
                }
                return '';
              }}
              onRow={
                params.calcPageKey == 'wholeHospCostCalculate'
                  ? (record: any) => ({
                      style: {
                        ['--report-font-color' as any]:
                          record?.fontColor || DEFAULT_FONT_COLOR,
                      } as React.CSSProperties,
                    })
                  : undefined
              }
              scroll={{ x: scrollX, y: mergedY }}
              params={tableDataFilterParams}
              request={(params) => getTableData(params)}
              pagination={
                params.calcPageKey == 'wholeHospCostCalculate'
                  ? false
                  : params.calcPageKey == 'deptDirectMedicalCost'
                  ? false
                  : undefined
              }
              {...restTableProps}
              summary={(pageData: any[]) => {
                // 仅对 deptDirectMedicalCost / deptCostAllocationSummary 固定底部合计
                if (
                  params.calcPageKey !== 'deptDirectMedicalCost' &&
                  params.calcPageKey !== 'deptCostAllocationSummary'
                )
                  return undefined;
                // 由于该页不分页，这里的合计为当前渲染数据的总计
                try {
                  // 如果接口有“总计”行，优先用它并固定到底部
                  if (bottomSummaryRow) {
                    return (
                      <Table.Summary fixed>
                        <Table.Summary.Row className="total-summary-row">
                          <Table.Summary.Cell index={0}>
                            总计
                          </Table.Summary.Cell>
                          {params.calcPageKey === 'deptDirectMedicalCost' ? (
                            <>
                              <Table.Summary.Cell index={1} align="right">
                                {formatMoneyNumber(
                                  bottomSummaryRow.personnelExpense,
                                  {
                                    decimalPlaces:
                                      typeof bottomSummaryRow?.decimalPlace ===
                                      'number'
                                        ? bottomSummaryRow.decimalPlace
                                        : 2,
                                    useThousandSeparator:
                                      bottomSummaryRow?.permil === 1 ||
                                      bottomSummaryRow?.permil === true,
                                  },
                                )}
                              </Table.Summary.Cell>
                              <Table.Summary.Cell index={2} align="right">
                                {formatMoneyNumber(
                                  bottomSummaryRow.healthMaterialFee,
                                  {
                                    decimalPlaces:
                                      typeof bottomSummaryRow?.decimalPlace ===
                                      'number'
                                        ? bottomSummaryRow.decimalPlace
                                        : 2,
                                    useThousandSeparator:
                                      bottomSummaryRow?.permil === 1 ||
                                      bottomSummaryRow?.permil === true,
                                  },
                                )}
                              </Table.Summary.Cell>
                              <Table.Summary.Cell index={3} align="right">
                                {formatMoneyNumber(bottomSummaryRow.drugFee, {
                                  decimalPlaces:
                                    typeof bottomSummaryRow?.decimalPlace ===
                                    'number'
                                      ? bottomSummaryRow.decimalPlace
                                      : 2,
                                  useThousandSeparator:
                                    bottomSummaryRow?.permil === 1 ||
                                    bottomSummaryRow?.permil === true,
                                })}
                              </Table.Summary.Cell>
                              <Table.Summary.Cell index={4} align="right">
                                {formatMoneyNumber(
                                  bottomSummaryRow.fixedAssetDepreciation,
                                  {
                                    decimalPlaces:
                                      typeof bottomSummaryRow?.decimalPlace ===
                                      'number'
                                        ? bottomSummaryRow.decimalPlace
                                        : 2,
                                    useThousandSeparator:
                                      bottomSummaryRow?.permil === 1 ||
                                      bottomSummaryRow?.permil === true,
                                  },
                                )}
                              </Table.Summary.Cell>
                              <Table.Summary.Cell index={5} align="right">
                                {formatMoneyNumber(
                                  bottomSummaryRow.intangibleAssetAmortization,
                                  {
                                    decimalPlaces:
                                      typeof bottomSummaryRow?.decimalPlace ===
                                      'number'
                                        ? bottomSummaryRow.decimalPlace
                                        : 2,
                                    useThousandSeparator:
                                      bottomSummaryRow?.permil === 1 ||
                                      bottomSummaryRow?.permil === true,
                                  },
                                )}
                              </Table.Summary.Cell>
                              <Table.Summary.Cell index={6} align="right">
                                {formatMoneyNumber(
                                  bottomSummaryRow.medicalRiskFundExtraction,
                                  {
                                    decimalPlaces:
                                      typeof bottomSummaryRow?.decimalPlace ===
                                      'number'
                                        ? bottomSummaryRow.decimalPlace
                                        : 2,
                                    useThousandSeparator:
                                      bottomSummaryRow?.permil === 1 ||
                                      bottomSummaryRow?.permil === true,
                                  },
                                )}
                              </Table.Summary.Cell>
                              <Table.Summary.Cell index={7} align="right">
                                {formatMoneyNumber(
                                  bottomSummaryRow.otherMedicalExpenses,
                                  {
                                    decimalPlaces:
                                      typeof bottomSummaryRow?.decimalPlace ===
                                      'number'
                                        ? bottomSummaryRow.decimalPlace
                                        : 2,
                                    useThousandSeparator:
                                      bottomSummaryRow?.permil === 1 ||
                                      bottomSummaryRow?.permil === true,
                                  },
                                )}
                              </Table.Summary.Cell>
                              <Table.Summary.Cell index={8} align="right">
                                {formatMoneyNumber(bottomSummaryRow.total, {
                                  decimalPlaces:
                                    typeof bottomSummaryRow?.decimalPlace ===
                                    'number'
                                      ? bottomSummaryRow.decimalPlace
                                      : 2,
                                  useThousandSeparator:
                                    bottomSummaryRow?.permil === 1 ||
                                    bottomSummaryRow?.permil === true,
                                })}
                              </Table.Summary.Cell>
                            </>
                          ) : (
                            <>
                              <Table.Summary.Cell index={1} align="right">
                                {formatMoneyNumber(
                                  bottomSummaryRow.medicalCost,
                                  {
                                    decimalPlaces:
                                      typeof bottomSummaryRow?.decimalPlace ===
                                      'number'
                                        ? bottomSummaryRow.decimalPlace
                                        : 2,
                                    useThousandSeparator: true,
                                  },
                                )}
                              </Table.Summary.Cell>
                              <Table.Summary.Cell index={2} align="right">
                                {formatMoneyNumber(
                                  bottomSummaryRow.directCost,
                                  {
                                    decimalPlaces:
                                      typeof bottomSummaryRow?.decimalPlace ===
                                      'number'
                                        ? bottomSummaryRow.decimalPlace
                                        : 2,
                                    useThousandSeparator: true,
                                  },
                                )}
                              </Table.Summary.Cell>
                              <Table.Summary.Cell index={3} align="right">
                                {formatMoneyNumber(bottomSummaryRow.subtotal, {
                                  decimalPlaces:
                                    typeof bottomSummaryRow?.decimalPlace ===
                                    'number'
                                      ? bottomSummaryRow.decimalPlace
                                      : 2,
                                  useThousandSeparator: true,
                                })}
                              </Table.Summary.Cell>
                              <Table.Summary.Cell index={4} align="right">
                                {formatMoneyNumber(
                                  bottomSummaryRow.allocatedAdminCost,
                                  {
                                    decimalPlaces:
                                      typeof bottomSummaryRow?.decimalPlace ===
                                      'number'
                                        ? bottomSummaryRow.decimalPlace
                                        : 2,
                                    useThousandSeparator: true,
                                  },
                                )}
                              </Table.Summary.Cell>
                              <Table.Summary.Cell index={5} align="right">
                                {formatMoneyNumber(
                                  bottomSummaryRow.allocatedSupportCost,
                                  {
                                    decimalPlaces:
                                      typeof bottomSummaryRow?.decimalPlace ===
                                      'number'
                                        ? bottomSummaryRow.decimalPlace
                                        : 2,
                                    useThousandSeparator: true,
                                  },
                                )}
                              </Table.Summary.Cell>
                              <Table.Summary.Cell index={6} align="right">
                                {formatMoneyNumber(
                                  bottomSummaryRow.allocatedTechCost,
                                  {
                                    decimalPlaces:
                                      typeof bottomSummaryRow?.decimalPlace ===
                                      'number'
                                        ? bottomSummaryRow.decimalPlace
                                        : 2,
                                    useThousandSeparator: true,
                                  },
                                )}
                              </Table.Summary.Cell>
                            </>
                          )}
                        </Table.Summary.Row>
                      </Table.Summary>
                    );
                  }
                  // 数值列 key 列表
                  const amountKeys =
                    params.calcPageKey === 'deptDirectMedicalCost'
                      ? [
                          'personnelExpense',
                          'healthMaterialFee',
                          'drugFee',
                          'fixedAssetDepreciation',
                          'intangibleAssetAmortization',
                          'medicalRiskFundExtraction',
                          'otherMedicalExpenses',
                          'total',
                        ]
                      : [
                          'medicalCost',
                          'directCost',
                          'subtotal',
                          'allocatedAdminCost',
                          'allocatedSupportCost',
                          'allocatedTechCost',
                        ];
                  const sums: Record<string, number> = {};
                  (Array.isArray(pageData) ? pageData : [])?.forEach?.(
                    (row: any) => {
                      amountKeys.forEach((k) => {
                        const v = Number(row?.[k] ?? 0);
                        sums[k] = (sums[k] || 0) + (isNaN(v) ? 0 : v);
                      });
                    },
                  );
                  return (
                    <Table.Summary fixed>
                      <Table.Summary.Row className="total-summary-row">
                        <Table.Summary.Cell index={0}>合计</Table.Summary.Cell>
                        {params.calcPageKey === 'deptDirectMedicalCost' ? (
                          <>
                            <Table.Summary.Cell index={1} align="right">
                              {formatMoneyNumber(sums.personnelExpense, {
                                decimalPlaces: 2,
                                useThousandSeparator: true,
                              })}
                            </Table.Summary.Cell>
                            <Table.Summary.Cell index={2} align="right">
                              {formatMoneyNumber(sums.healthMaterialFee, {
                                decimalPlaces: 2,
                                useThousandSeparator: true,
                              })}
                            </Table.Summary.Cell>
                            <Table.Summary.Cell index={3} align="right">
                              {formatMoneyNumber(sums.drugFee, {
                                decimalPlaces: 2,
                                useThousandSeparator: true,
                              })}
                            </Table.Summary.Cell>
                            <Table.Summary.Cell index={4} align="right">
                              {formatMoneyNumber(sums.fixedAssetDepreciation, {
                                decimalPlaces: 2,
                                useThousandSeparator: true,
                              })}
                            </Table.Summary.Cell>
                            <Table.Summary.Cell index={5} align="right">
                              {formatMoneyNumber(
                                sums.intangibleAssetAmortization,
                                {
                                  decimalPlaces: 2,
                                  useThousandSeparator: true,
                                },
                              )}
                            </Table.Summary.Cell>
                            <Table.Summary.Cell index={6} align="right">
                              {formatMoneyNumber(
                                sums.medicalRiskFundExtraction,
                                {
                                  decimalPlaces: 2,
                                  useThousandSeparator: true,
                                },
                              )}
                            </Table.Summary.Cell>
                            <Table.Summary.Cell index={7} align="right">
                              {formatMoneyNumber(sums.otherMedicalExpenses, {
                                decimalPlaces: 2,
                                useThousandSeparator: true,
                              })}
                            </Table.Summary.Cell>
                            <Table.Summary.Cell index={8} align="right">
                              {formatMoneyNumber(sums.total, {
                                decimalPlaces: 2,
                                useThousandSeparator: true,
                              })}
                            </Table.Summary.Cell>
                          </>
                        ) : (
                          <>
                            <Table.Summary.Cell index={1} align="right">
                              {formatMoneyNumber(sums.medicalCost, {
                                decimalPlaces: 2,
                                useThousandSeparator: true,
                              })}
                            </Table.Summary.Cell>
                            <Table.Summary.Cell index={2} align="right">
                              {formatMoneyNumber(sums.directCost, {
                                decimalPlaces: 2,
                                useThousandSeparator: true,
                              })}
                            </Table.Summary.Cell>
                            <Table.Summary.Cell index={3} align="right">
                              {formatMoneyNumber(sums.subtotal, {
                                decimalPlaces: 2,
                                useThousandSeparator: true,
                              })}
                            </Table.Summary.Cell>
                            <Table.Summary.Cell index={4} align="right">
                              {formatMoneyNumber(sums.allocatedAdminCost, {
                                decimalPlaces: 2,
                                useThousandSeparator: true,
                              })}
                            </Table.Summary.Cell>
                            <Table.Summary.Cell index={5} align="right">
                              {formatMoneyNumber(sums.allocatedSupportCost, {
                                decimalPlaces: 2,
                                useThousandSeparator: true,
                              })}
                            </Table.Summary.Cell>
                            <Table.Summary.Cell index={6} align="right">
                              {formatMoneyNumber(sums.allocatedTechCost, {
                                decimalPlaces: 2,
                                useThousandSeparator: true,
                              })}
                            </Table.Summary.Cell>
                          </>
                        )}
                      </Table.Summary.Row>
                    </Table.Summary>
                  );
                } catch {
                  return undefined;
                }
              }}
            />
          );
        })()}
        {totalCount != undefined && (
          <a
            style={{ marginTop: 16, display: 'inline-block' }}
          >{`合计：${formatMoneyNumber(totalCount)}`}</a>
        )}
      </div>
    </KCIMPagecontainer>
  );
}
