<template>
  <a-row id="has_row" type="flex" :gutter="dynamicGutter" :style="isWidget ? {margin: '0px'} : {'margin-bottom': '.5rem'}">
    <template v-for="(cell, cellIndex) in columns">
      <a-col
        name="trGroup"
        v-if="Array.isArray(cell) || !cell.dontShowRow"
        :key="cellIndex"
        :ref="`trGroup_${ cell.slotRef || cellIndex}`"
        @hook:mounted="(h)=>applyAllStyles(cell,cellIndex)"
        :span="calculateColSpan(cell, columns)">
        <div id="report_widget" v-if="isWidget">
          <!-- 插槽渲染 -->
          <template v-if="Array.isArray(cell)">
            <!-- 处理 cell 是数组的情况 -->
            <div v-for="(item, index) in cell" :key="index">
              <x-report-tr-group
                :env="env"
                :key="index"
                :columns="recalculateItem(item)"
                :config-data="configData"
                :config="config"
                :display="true">
              </x-report-tr-group>
            </div>
          </template>
          <template v-else-if="cell.type === 'slot'">
            <template
              v-if="[
                'x-form-table',
                'h-form-table',
                'x-add-native-form',
                'h-add-native-form',
                'x-tree-pro',
                'x-his-editor',
                'h-form',
                'x-tab',
                'h-tab',
                'x-form-group',
                'h-form-group',
                'x-report',
                'x-buttons',
                'h-buttons',
                'x-label-select',
                'x-conversation',
                'x-check-list',
                'x-cardSet',
                'x-collapse',
                'x-h-descriptions',
                'x-sidebar',
                'x-list',
                'x-input',
                'x-time-line',
                'x-radio',
                'x-calendar',
                'x-time-select',
                'x-checkbox',
                'x-title',
                'x-select',
                'x-tree-rows',
                'x-three-test-orders',
                'x-shift-schedule',
                'x-charge',
                'x-questionnaire',
                'x-import-excel-button',
                'x-chart',
                'h-chart',
                'x-simple-table',
                'x-workflow-progress',
                'h-ai',
                'x-markdown',
                'x-markdown-section',
                'x-transfer'
              ].includes(cell.slotType)">
              <component
                :is="getComponentName(cell.slotConfig, cell.serviceName, cell.slotType)"
                :key="cellIndex"
                :ref="`dynamicComponent_${ cell.slotRef || cellIndex}`"
                v-bind="cell.attrs"
                :serviceName="cell.serviceName"
                :serverName="cell.serviceName"
                v-on="getEventHandlers(cell, cellIndex)"
                @configEnd="onSlotConfigEnd(cellIndex)"
                @hook:mounted="(h)=>onComponentMounted(h,cell,cellIndex)"
                @beforeDataChange="beforeDataChange"
                @rowClick="handleRowClick"
                @onExpand="onExpand"
                :queryParamsName="cell.slotConfig"
                :configName="cell.slotConfig"
                :countVisible="false"
                :env="env"
              />
            </template>
          </template>
        </div>
        <a-card v-else class="flexItem" :bordered="false" :body-style="{ padding: 0 }">
          <!-- 插槽渲染 -->
          <template v-if="Array.isArray(cell)">
            <!-- 处理 cell 是数组的情况 -->
            <div v-for="(item, index) in cell" :key="index">
              <x-report-tr-group
                :server-name="serverName"
                :env="env"
                :key="index"
                :columns="recalculateItem(item)"
                :config-data="configData"
                :config="config"
                :display="true">
              </x-report-tr-group>
            </div>
          </template>
          <template v-else-if="cell.type === 'slot'">
            <template
              v-if="[
                'x-form-table',
                'h-form-table',
                'x-add-native-form',
                'h-add-native-form',
                'h-form',
                'x-tree-pro',
                'x-his-editor',
                'x-tab',
                'h-tab',
                'x-form-group',
                'h-form-group',
                'x-report',
                'x-buttons',
                'h-buttons',
                'x-label-select',
                'x-conversation',
                'x-check-list',
                'x-cardSet',
                'x-collapse',
                'x-h-descriptions',
                'x-sidebar',
                'x-list',
                'x-input',
                'x-time-line',
                'x-radio',
                'x-calendar',
                'x-time-select',
                'x-checkbox',
                'x-title',
                'x-select',
                'x-tree-rows',
                'x-three-test-orders',
                'x-shift-schedule',
                'x-charge',
                'x-questionnaire',
                'x-import-excel-button',
                'x-chart',
                'h-chart',
                'x-simple-table',
                'x-workflow-progress',
                'h-ai',
                'x-markdown',
                'x-markdown-section',
                'x-transfer'
              ].includes(cell.slotType)">
              <component
                :is="getComponentName(cell.slotConfig, cell.serviceName, cell.slotType)"
                :key="cellIndex"
                :ref="`dynamicComponent_${ cell.slotRef || cellIndex}`"
                v-bind="cell.attrs"
                :serviceName="cell.serviceName"
                :serverName="cell.serviceName"
                v-on="getEventHandlers(cell, cellIndex)"
                @configEnd="onSlotConfigEnd(cellIndex)"
                @hook:mounted="(h)=>onComponentMounted(h,cell,cellIndex)"
                @beforeDataChange="beforeDataChange"
                @rowClick="handleRowClick"
                @onExpand="onExpand"
                :queryParamsName="cell.slotConfig"
                :configName="cell.slotConfig"
                :countVisible="false"
                :env="env"
              />
            </template>
          </template>
        </a-card>
      </a-col>
    </template>
  </a-row>
</template>

<script>
import Upload from '@vue2-client/base-client/components/common/Upload'
import { getRealKeyData } from '@vue2-client/utils/util'
import { executeStrFunctionByContext } from '@vue2-client/utils/runEvalFunction'
import { getConfigByName, runLogic } from '@vue2-client/services/api/common'
import { getMicroData, getWindow, isMicroAppEnv, microDispatch } from '@vue2-client/utils/microAppUtils'
import { shortcutMixin } from '@vue2-client/base-client/plugins/shortcutMixin'

export default {
  name: 'XReportTrGroup',
  mixins: [shortcutMixin],
  components: {
    Upload,
    XFormTable: () => import('@vue2-client/base-client/components/common/XFormTable/XFormTable.vue'),
    HFormTable: () => import('@vue2-client/base-client/components/common/HIS/HFormTable/HFormTable.vue'),
    HForm: () => import('@vue2-client/base-client/components/common/HIS/HForm/HForm.vue'),
    XAddNativeForm: () => import('@vue2-client/base-client/components/common/XAddNativeForm/XAddNativeForm.vue'),
    HAddNativeForm: () => import('@vue2-client/base-client/components/common/HIS/HAddNativeForm/HAddNativeForm.vue'),
    XFormGroup: () => import('@vue2-client/base-client/components/common/XFormGroup/XFormGroup.vue'),
    HFormGroup: () => import('@vue2-client/base-client/components/common/HIS/HFormGroup/HFormGroup.vue'),
    XTreePro: () => import('@vue2-client/base-client/components/common/XTree/XTreePro.vue'),
    XHisEditor: () => import('@vue2-client/base-client/components/his/XHisEditor/XHisEditor.vue'),
    XTab: () => import('@vue2-client/base-client/components/common/XTab/XTab.vue'),
    HTab: () => import('@vue2-client/base-client/components/common/HIS/HTab/HTab.vue'),
    XReport: () => import('@vue2-client/base-client/components/common/XReport/XReport.vue'),
    XButtons: () => import('@vue2-client/base-client/components/common/XButtons/XButtons.vue'),
    HButtons: () => import('@vue2-client/base-client/components/common/HIS/HButtons/HButtons.vue'),
    XLabelSelect: () => import('@vue2-client/base-client/components/common/XLabelSelect/XLabelSelect.vue'),
    XConversation: () => import('@vue2-client/base-client/components/common/XConversation/XConversation.vue'),
    XCheckList: () => import('@vue2-client/base-client/components/common/XCheckList/XCheckList.vue'),
    XCardSet: () => import('@vue2-client/base-client/components/common/XCardSet/XCardSet.vue'),
    XCollapse: () => import('@vue2-client/base-client/components/common/XCollapse/XCollapse.vue'),
    XHDescriptions: () => import('@vue2-client/base-client/components/his/XHDescriptions/XHDescriptions.vue'),
    XSidebar: () => import('@vue2-client/base-client/components/his/XSidebar/XSidebar.vue'),
    XList: () => import('@vue2-client/base-client/components/his/XList/XList.vue'),
    XInput: () => import('@vue2-client/base-client/components/common/XInput/XInput.vue'),
    XTimeLine: () => import('@vue2-client/base-client/components/common/XTimeline/XTimeline.vue'),
    XRadio: () => import('@vue2-client/base-client/components/his/XRadio/XRadio.vue'),
    XCalendar: () => import('@vue2-client/base-client/components/common/XCalendar/XCalendar.vue'),
    XTimeSelect: () => import('@vue2-client/base-client/components/his/XTimeSelect/XTimeSelect.vue'),
    XCheckbox: () => import('@vue2-client/base-client/components/his/XCheckbox/XCheckbox.vue'),
    XTitle: () => import('@vue2-client/base-client/components/his/XTitle/XTitle.vue'),
    XSelect: () => import('@vue2-client/base-client/components/his/XSelect/XSelect.vue'),
    XTreeRows: () => import('@vue2-client/base-client/components/his/XTreeRows/XTreeRows.vue'),
    XThreeTestOrders: () => import('@vue2-client/base-client/components/his/threeTestOrders/threeTestOrders.vue'),
    XShiftSchedule: () => import('@vue2-client/base-client/components/his/XShiftSchedule/XShiftSchedule.vue'),
    XCharge: () => import('@vue2-client/base-client/components/his/XCharge/XCharge.vue'),
    XQuestionnaire: () => import('@vue2-client/base-client/components/his/XQuestionnaire/XQuestionnaire.vue'),
    XImportExcelButton: () => import('@vue2-client/base-client/components/his/XImportExcelButton/XImportExcelButton.vue'),
    XChart: () => import('@vue2-client/base-client/components/his/XChart/XChart.vue'),
    HChart: () => import('@vue2-client/base-client/components/his/HChart/HChart.vue'),
    XSimpleTable: () => import('@vue2-client/base-client/components/his/XSimpleTable/XSimpleTable.vue'),
    XWorkflowProgress: () => import('@vue2-client/base-client/components/his/XWorkflowProgress/XWorkflowProgress.vue'),
    HAi: () => import('@vue2-client/base-client/components/his/HAi/HAi.vue'),
    XMarkdown: () => import('@vue2-client/base-client/components/common/XMarkdownViewer/XMarkdownViewer.vue'),
    XMarkdownSection: () => import('@vue2-client/base-client/components/common/XMarkdownSectionExtractor/XMarkdownSectionExtractor.vue'),
    XTransfer: () => import('@vue2-client/base-client/components/his/XTransfer/XTransfer.vue')
  },
  props: {
    // 每一行的配置
    columns: {
      type: Array,
      required: true
    },
    showImgInCell: {
      type: Boolean,
      default: false
    },
    config: {
      type: Object,
      default: function () {
        return {}
      }
    },
    // 命名空间
    serverName: {
      type: String,
      default: process.env.VUE_APP_SYSTEM_NAME
    },
    // 环境
    env: {
      type: String,
      default: 'prod'
    },
    // 原始配置
    configData: {
      type: Object,
      required: true
    },
    // 是否为展示行
    display: {
      type: Boolean,
      default: false
    },
  },
  computed: {
    allSlotSum () {
      // 计算总共有多少个Slot
      let sum = 0
      this.columns.forEach((item) => {
        if (Array.isArray(item)) {
          item.forEach((cell) => {
            if (cell.type === 'slot') {
              sum++
            }
          })
        } else if (item.type && item.type === 'slot') {
          sum++
        }
      })
      return sum
    },
    // 动态 gutter 配置：当包含 x-sidebar 时禁用 gutter
    dynamicGutter () {
      if (this.config.enableGutter === false || this.config.enableGutter === 'false') {
        return 0
      }
      if (!this.config || !this.config.columns || !Array.isArray(this.config.columns)) {
        return this.gutter
      }
      // 检查是否包含 x-sidebar 组件
      const hasXSidebar = this.config.columns.some(row => {
        if (!Array.isArray(row)) return false
        return row.some(cell => {
          if (Array.isArray(cell)) {
            const found = cell.some(item => item.slotType === 'x-sidebar')
            return found
          }
          const found = cell.slotType === 'x-sidebar'
          return found
        })
      })
      const result = !hasXSidebar
      return result ? this.gutter : 0
    }
  },
  data () {
    return {
      // 快捷键作用域类型：grid 表示栅格类组件
      shortcutScopeType: 'grid',
      gutter: [8, { xs: 8, sm: 16, md: 24, lg: 32 }], // 设置水槽大小
      maxColSpan: 12,
      uploadParams: {
        type: 'image',
        accept: ['*'],
        resUploadStock: 1,
        pathKey: 'cs'
      },
      mixinData: {},
      flexItemBodyState: {},
      // 已经渲染得插槽得数量
      slotRendered: 0,
      // 已发出 configEnd 的 slot 的 cellIndex 集合，用于统计「所有 slot 配置结束」
      slotConfigEnded: {},
      // tableConfig: {}
    }
  },
  watch: {
    columns: {
      deep: true,
      immediate: true,
      handler (newVal) {
        // 使用nextTick确保DOM更新
        this.$nextTick(() => {
          this.$forceUpdate()
        })
      }
    }
  },
  inject: {
    openDialog: { default: false },
    openDrawer: { default: false },
    emitEvent: { default: false },
    registerComponent: { default: false },
    setColSpanByName: { default: false },
    setGlobalData: { default: false },
    getGlobalData: { default: false },
    getComponentByName: { default: false },
    getParentComponentByName: { default: false },
    runLogic: { default: false },
    getMixinData: { default: false },
    getSelectedId: { default: false },
    isInAModal: { default: false },
    getConfigByName: { default: false },
    getSelectedData: { default: false },
    getOutEnv: { default: false },
    currUser: { default: false },
    isWidget: { default: false },
    findComponentByName: { default: false },
    closeAddReport: { default: false },
    setData: { default: false },
    getRootReport: { default: false },
    // 注入来自父组件（XReport）的栅格完整作用域路径（XReport已拼接完整）
    getGridScopePath: { default: null }
  },
  beforeDestroy() {
    this.unregisterShortcuts()
  },
  methods: {
    getWindow,
    isMicroAppEnv,
    microDispatch,
    getMicroData,
    getRealKeyData,
    // ========== Mixin 覆盖方法 ==========
    /**
     * 获取快捷键配置（覆盖mixin）
     * 验证当前激活的配置名是否匹配当前组件的配置名
     */
    getShortcutConfig() {
      try {
        let parent = ''
        if (typeof this.getGridScopePath === 'function') {
          parent = this.getGridScopePath()
        }
        const parts = parent.split('/')
        return { columns: this.columns, configName: parts[parts.length - 1], scopeType: 'grid' }
      }catch (e){
        console.log('=============---->',e)
      }
    },


    /**
     * 获取组件实例（覆盖mixin，供快捷键上下文使用）
     */
    getScopePath() {
      // 1. 获取路由
      const route = this.$route?.path || 'unknown-route'

      // 2. 获取 Tab 容器名称（来自 XTab）
      let tabInfo = 'no-tab'
      if (typeof this.getTabPath === 'function') {
        const tabPath = this.getTabPath()
        if (tabPath) {
          tabInfo = tabPath
        }
      } else if (typeof this.getCurrentTabIndex === 'function') {
        const tabIndex = this.getCurrentTabIndex()
        if (tabIndex !== undefined && tabIndex !== null) {
          tabInfo = `tab[${tabIndex}]`
        }
      }

      // 3. 获取栅格配置名称 - 优先使用根组件的 configName，否则尝试 config 上的属性
      let gridName = 'unknown-grid'
      if (this._rootConfigName) {
        gridName = this._rootConfigName
      } else if (this.config) {
        // 尝试 configName
        if (this.config.configName) {
          gridName = this.config.configName
        }
        // 尝试 configKey
        else if (this.config.configKey) {
          gridName = this.config.configKey
        }
        // 尝试 slotConfigName
        else if (this.config.slotConfigName) {
          gridName = this.config.slotConfigName
        }
        // 尝试 name
        else if (this.config.name) {
          gridName = this.config.name
        }
        // 尝试 title
        else if (this.config.title) {
          gridName = this.config.title
        }
        // 尝试从 columns 中的第一个 slot 获取 slotConfig（槽位名）
        else if (this.config.columns && this.config.columns.length > 0) {
          const firstRow = this.config.columns[0]
          if (Array.isArray(firstRow) && firstRow.length > 0) {
            const firstCell = firstRow[0]
            if (firstCell?.slotConfig) {
              gridName = `slot:${firstCell.slotConfig}`
            } else if (firstCell?.slotRef) {
              gridName = `ref:${firstCell.slotRef}`
            }
          }
        }
      }

      // 调试：打印 config 的可用属性
      if (this._scopePathDebugCount === undefined) {
        this._scopePathDebugCount = 0
      }
      if (this._scopePathDebugCount < 3 && this.config) {
        console.log(`[XReportTrGroup getScopePath] config keys:`, Object.keys(this.config), 'configName:', this.config.configName)
        this._scopePathDebugCount++
      }

      // 完整路径：路由 -> Tab容器名称 -> 栅格配置名称
      return `${route} -> ${tabInfo} -> ${gridName}`
    },

    /**
     * 获取组件实例（覆盖mixin，供快捷键上下文使用）
     */
    shortcutGetComponent(ref) {
      // 通过 $refs 查找动态组件
      const refName = `dynamicComponent_${ref}`
      const component = this.$refs[refName]?.[0]
      console.log('【获取组件实例】',component)
      if (component) {
        // 尝试获取实例方法
        if (component.getXTabInstance) return component.getXTabInstance()
        if (component.getXFormTableInstance) return component.getXFormTableInstance()
        if (component.getXAddNativeFormInstance) return component.getXAddNativeFormInstance()
        return component
      }
      return null
    },

    /**
     * 查找组件（覆盖mixin）
     */
    shortcutFindComponent(ref) {
      console.log('【查找组件】', this)
      console.log('【查找组件】', ref)
      if (this.findComponentByName) {
        return this.findComponentByName(this, ref, 10, 'parent')
      }
      return this.shortcutGetComponent(ref)
    },
    // ========== Mixin 覆盖方法结束 ==========
    handleRowClick (record) {
      this.$emit('rowClick', record)
    },
    beforeDataChange (record) {
      this.$emit('beforeDataChange', record)
    },
    onExpand (expanded, record) {
      this.$emit('expand', expanded, record)
    },
    listClick (data) {
      this.$emit('listClick', data)
    },
    calculateColSpan (cell, columns) {
      // 1. 获取当前 cell 的原始 colSpan 值
      const currentColSpan = Array.isArray(cell)
        ? cell[0][0]?.colSpan || 1
        : (cell?.colSpan ?? cell?.def?.colSpan ?? 1)

      // 2. 计算整行所有 cell 的 colSpan 总和
      const totalColSpan = columns.reduce((sum, c) => {
        const span = Array.isArray(c)
          ? c[0][0]?.colSpan || 1
          : (c?.colSpan ?? c?.def?.colSpan ?? 1)
        return sum + span
      }, 0)

      // 3. 智能判断：总和 > 12 为新配置（24份），≤ 12 为旧配置（12份需要×2）
      const multiplier = totalColSpan > 12 ? 1 : 2

      return currentColSpan * multiplier
    },
    applyAllStyles (cell, cellIndex) {
      // 应用组件样式
      const component = this.$refs[`trGroup_${ cell.slotRef || cellIndex}`][0]
      // 确保组件已经完全挂载
      this.$nextTick(() => {
        this.applyComponentStyles(component, cell, cellIndex)
      })
    },
    onSlotConfigEnd (cellIndex) {
      if (this.slotConfigEnded[cellIndex]) return
      this.$set(this.slotConfigEnded, cellIndex, true)
      if (Object.keys(this.slotConfigEnded).length >= this.allSlotSum) {
        this.$emit('slotsConfigEnded')
        // 所有 slot 配置结束后，完整扫描一次快捷键
        this.$nextTick(() => {
          console.log('【所有 slot 配置结束后】 完整扫描一次快捷键')
          this.rescanShortcuts()
        })
      }
    },
    onComponentMounted (h, cell, cellIndex) {
      this.slotRendered += 1
      if (this.slotRendered >= this.allSlotSum) {
        this.$emit('slotRendered')
      }
      if (this.getMixinData && this.getMixinData()) {
        this.mixinData = this.getMixinData()
      }
      if (cell.slotRef && this.registerComponent) {
        this.registerComponent(cell.slotRef, this.$refs[`dynamicComponent_${cell.slotRef || cellIndex}`][0], {
          globalRegistryName: cell.globalRegistryName,
          mountedLogicName: cell.mountedLogicName,
          mountedLogicMode: cell.mountedLogicMode,
          mountedLogicParam: cell.mountedLogicParam
        })}
      // 子组件挂载后，触发其快捷键注册
      const component = this.$refs[`dynamicComponent_${cell.slotRef || cellIndex}`]?.[0]
      console.log('【子组件挂载后，触发其快捷键注册】', component)
      if (component && typeof component.onShortcutMixinReady === 'function') {
        component.onShortcutMixinReady()
      }
      // 传递给祖先组件
      const shouldInit = cell.shouldInit == null ? true : cell.shouldInit
      if (shouldInit) {
        if (cell.slotType === 'x-add-native-form' || cell.slotType === 'h-form') {
          // 简易表单需要主动调用初始化方法
          getConfigByName(cell.slotConfig, cell.serviceName, async (res) => {
            // 如果配置了 表单初始化logic
            // 调用 logic 获取参数
            let param = { ...this.mixinData }
            let selectedId
            if (res.paramLogicName) {
              if (!!this.getSelectedId) {
                selectedId = this.getSelectedId()
                if (typeof selectedId !== 'object') {
                  selectedId = { selectedId: selectedId }
                }
              }
              param = Object.assign(param, await runLogic(res.paramLogicName, selectedId, cell.serviceName))
            }
            this.$refs[`dynamicComponent_${cell.slotRef || cellIndex}`][0].init({
              serviceName: cell.serviceName,
              configName: cell.slotConfig,
              formItems: res.formJson,
              showSubmitBtn: !this.isInAModal,
              businessType: param.businessType || '新增',
              layout: res.xAddFormLayout,
              primaryKey: res.primaryKey,
              ...res,
              fixedAddForm: param,
              modifyModelData: {
                files: param.files,
                images: param.images
              }
            })
          }, this.env === 'dev')
        } else if (cell.slotType === 'x-form-group') {
          // 简易表单需要主动调用初始化方法
          getConfigByName(cell.slotConfig, cell.serviceName, (res) => {
            // 如果配置了 表单初始化logic
            // 调用 logic 获取参数
            const param = { ...this.mixinData }
            this.$refs[`dynamicComponent_${cell.slotRef || cellIndex}`][0].init({
              ...res,
              serviceName: cell.serviceName,
              showSubmitBtn: !this.isInAModal,
              businessType: param.businessType || '新增',
              modifyModelData: param,
              showLeftTab: true,
            })
          }, this.env === 'dev')
        } else if (cell.slotType === 'x-label-select') {
          // 按钮组需要主动调用初始化方法
          getConfigByName(cell.slotConfig, cell.serviceName, (res) => {
            this.$refs[`dynamicComponent_${cell.slotRef || cellIndex}`][0].init({
              ...res,
              serviceName: cell.serviceName,
            })
          }, this.env === 'dev')
        }
      }
      if (cell.slotType === 'x-report') {
        const param = { ...this.mixinData }
        this.$refs[`dynamicComponent_${cell.slotRef || cellIndex}`][0].init({
          configName: cell.slotConfig,
          configData: param
        })
      }
      if (cell.slotType === 'x-conversation') {
        getConfigByName(cell.slotConfig, cell.serviceName, (res) => {
          this.$refs[`dynamicComponent_${cell.slotRef || cellIndex}`][0].init({
            serviceName: cell.serviceName,
            ...res,
          })
        }, this.env === 'dev')
      }
      if (cell.slotType === 'x-check-list') {
        getConfigByName(cell.slotConfig, cell.serviceName, (res) => {
          this.$refs[`dynamicComponent_${cell.slotRef || cellIndex}`][0].init({
            serviceName: cell.serviceName,
            ...res,
          })
        }, this.env === 'dev')
      }
    },
    recalculateItem (item) {
      const totalColSpan = item.reduce((sum, cell) => {
        // 保留手动设置的colSpan
        return sum + (cell._isManualColSpan ? 0 : (cell.colSpan || 1))
      }, 0)
      return item.map(cell => {
        // 跳过已手动设置的单元格
        if (cell._isManualColSpan) return cell
        const newColSpan = Math.round((cell.colSpan || 1) / totalColSpan * 12)
        return {
          ...cell,
          colSpan: newColSpan,
          // 标记自动计算的单元格
          _isAutoCalculated: true
        }
      })
    },

    getEventHandlers (cell, cellIndex) {
      const handlers = {}
      if (!cell?.events || cell?.events?.length === 0) {
        return handlers
      }
      cell.events.forEach(event => {
        handlers[event.type] = async (...args) => {
          let func = event.customFunction
          if (func && func.startsWith('function')) {
            func = func.replace('function', 'async function')
          }
          const result = await executeStrFunctionByContext(this, func, args)
          if (result instanceof Promise) {
            result.then((res) => {
              if (!res) return
              let messageType = 'success'
              // 如果传递了组件名字 自动调用刷新（getComponentByName 由根 XReport 注入并绑定，指向根 $refs）
              if (res?.name && this.getComponentByName) {
                const waitRefreshRef = this.getComponentByName(res.name)
                if (waitRefreshRef) {
                  waitRefreshRef.refresh()
                } else {
                  console.warn(`未找到组件${res.name}无法刷新`)
                }
              }
              // 如果传递消息类型 自动调用消息
              if (res?.messageType) {
                messageType = res.messageType
              }
              // 如果传递了提示信息自动调用提示
              if (res?.message) {
                this.$message[messageType](res?.message)
              }
            })
          }
        }
      })
      return handlers
    },
    getComponentName (queryParamsName, serviceName, componentName) {
      return componentName
    },
    // 判断单元格样式
    determineCellStyle (cell, color = '#000', borderWidth = '1px') {
      // 如果声明了borderColor
      if (this.config.style.borderColor) {
        color = this.config.style.borderColor
      }
      let result = {}
      // 如果表格也声明了样式，用表格样式将样式覆盖
      if (cell.style) {
        if (cell.noBorder) {
          result = { ...cell.style }
        } else {
          if (this.noTopBorder) {
            result = { ...cell.style }
          } else {
            result = { ...cell.style }
          }
        }
        return result
      }
      return result
    },
    // 把用户定义的组件，传递到整个杉格中，方便调用
    passComponentNamesToAncestor (refs) {
      const findCellBySlotRef = (cols, slotRef) => {
        if (!Array.isArray(cols)) return cols && cols.slotRef === slotRef ? cols : null
        for (const c of cols) {
          if (c && !Array.isArray(c) && c.slotRef === slotRef) return c
          if (Array.isArray(c)) {
            const found = findCellBySlotRef(c, slotRef)
            if (found) return found
          }
        }
        return null
      }
      Object.entries(refs).forEach(([refKey, refValue]) => {
        if (refKey.startsWith('dynamicComponent_')) {
          const componentRef = refValue[0]
          if (componentRef && this.registerComponent) {
            const index = refKey.replace('dynamicComponent_', '')
            const cell = findCellBySlotRef(this.columns, index)
            this.registerComponent(index, componentRef, {
              globalRegistryName: cell?.globalRegistryName,
              mountedLogicName: cell?.mountedLogicName,
              mountedLogicMode: cell?.mountedLogicMode,
              mountedLogicParam: cell?.mountedLogicParam
            })
          }
        }
      })
    },
    // 获取组件样式配置
    async getComponentStyleConfig (componentType) {
      try {
        // 从配置中获取样式定义
        const publicStyleConfig = this.$appdata.getStylesByKey('public') || {}
        const styleConfig = this.$appdata.getStylesByKey(componentType) || {}
        Object.assign(publicStyleConfig, styleConfig)
        return publicStyleConfig
      } catch (error) {
        console.error('获取组件样式配置失败:', error)
        return {}
      }
    },

    // 解析组件样式配置
    async parseComponentStyles (cell) {
      if (!cell.class) return { rootStyles: {}, childStyles: {} }

      const styleConfig = await this.getComponentStyleConfig(cell.slotType)
      if (!styleConfig) return { rootStyles: {}, childStyles: {} }

      const rootStyles = {}
      const childStyles = new Map()

      // 处理每个class配置
      cell.class.split(' ').forEach(className => {
        const classConfig = styleConfig[className]
        if (!classConfig) return

        // 处理根节点样式
        Object.entries(classConfig).forEach(([key, value]) => {
          if (!key.startsWith('*') && typeof key !== 'object') {
            rootStyles[key] = value
          }
        })

        // 处理子节点样式
        this.parseNestedStyles(classConfig, childStyles)
      })
      return {
        rootStyles,
        childStyles
      }
    },

    // 递归解析嵌套的样式配置
    parseNestedStyles (config, styleMap, parentKey = '') {
      Object.entries(config).forEach(([key, value]) => {
        if (!key.startsWith('*')) return

        const className = key.replace('*', '.')

        // 如果值是对象，检查是否包含样式和子节点
        if (typeof value === 'object') {
          const { style = {}, children = {} } = this.separateStyleAndChildren(value)

          // 创建或获取当前节点的样式配置
          if (!styleMap.has(className)) {
            styleMap.set(className, {
              styles: {},
              children: new Map()
            })
          }

          const nodeData = styleMap.get(className)

          // 合并样式
          Object.assign(nodeData.styles, style)

          // 递归处理子节点
          this.parseNestedStyles(children, nodeData.children, className)
        }
      })
    },

    // 分离样式属性和子节点配置
    separateStyleAndChildren (obj) {
      const style = {}
      const children = {}

      Object.entries(obj).forEach(([key, value]) => {
        if (key.startsWith('*')) {
          // 子节点配置
          children[key] = value
        } else {
          // 样式属性
          style[key] = value
        }
      })

      return { style, children }
    },

    // 应用组件样式
    async applyComponentStyles (component, cell, cellIndex) {
      if (!component || !component.$el) return

      const { rootStyles, childStyles } = await this.parseComponentStyles(cell)

      // 应用根节点样式
      if (Object.keys(rootStyles).length > 0) {
        Object.entries(rootStyles).forEach(([property, value]) => {
          // 兼容 Ant Row gutter 在列上写入的行内 padding-left/right，
          // 这里同时写入四个方向的长属性，确保覆盖。
          if (property === 'padding') {
            component.$el.style.setProperty('padding', value, 'important')
            component.$el.style.setProperty('padding-left', value, 'important')
            component.$el.style.setProperty('padding-right', value, 'important')
            component.$el.style.setProperty('padding-top', value, 'important')
            component.$el.style.setProperty('padding-bottom', value, 'important')
          } else {
            component.$el.style.setProperty(property, value, 'important')
          }
        })
      }

      // 如果没有子节点样式,直接返回
      if (childStyles.size === 0) return

      let retryCount = 0
      const maxRetries = 5
      const retryInterval = 100 // 100ms

      const applyStyles = () => {
        this.applyChildStylesOptimized(component.$el, childStyles)
      }

      // 首次应用样式
      applyStyles()

      // 创建重试机制
      const retryApplyStyles = () => {
        if (retryCount >= maxRetries) return

        setTimeout(() => {
          applyStyles()
          retryCount++
          retryApplyStyles()
        }, retryInterval)
      }

      // 开始重试
      retryApplyStyles()

      // 创建 MutationObserver 用于动态内容
      const observer = new MutationObserver((mutations) => {
        // 检查是否有新增节点
        const hasNewNodes = mutations.some(mutation =>
          mutation.type === 'childList' && mutation.addedNodes.length > 0
        )
        const styleChanged = mutations.some(mutation =>
          mutation.type === 'attributes' && mutation.attributeName === 'style'
        )

        if (hasNewNodes || styleChanged) {
          // 重新应用根样式（处理 gutter 改写列 padding 的情况）
          if (Object.keys(rootStyles).length > 0) {
            Object.entries(rootStyles).forEach(([property, value]) => {
              if (property === 'padding') {
                component.$el.style.setProperty('padding', value, 'important')
                component.$el.style.setProperty('padding-left', value, 'important')
                component.$el.style.setProperty('padding-right', value, 'important')
                component.$el.style.setProperty('padding-top', value, 'important')
                component.$el.style.setProperty('padding-bottom', value, 'important')
              } else {
                component.$el.style.setProperty(property, value, 'important')
              }
            })
          }
          applyStyles()
        }
      })

      // 配置 observer
      observer.observe(component.$el, {
        childList: true,
        subtree: true,
        attributes: true,
        attributeFilter: ['style']
      })

      // 3秒后停止观察
      // setTimeout(() => {
      //   observer.disconnect()
      // }, 3000)

      // 组件销毁时清理
      this.$once('hook:beforeDestroy', () => {
        observer.disconnect()
      })
    },

    // 优化后的子节点样式应用方法
    applyChildStylesOptimized (rootElement, styleMap, parentSelector = '') {
      if (!rootElement) return

      // 处理样式映射
      try {
        for (const [selector, data] of styleMap.entries()) {
          const currentSelector = parentSelector ? `${parentSelector} ${selector}` : selector

          try {
            // 查找匹配的元素
            const elements = Array.from(rootElement.querySelectorAll(currentSelector))

            if (!elements.length) continue

            // 应用当前层级样式
            if (data.styles) {
              elements.forEach(element => {
                if (!element) return

                // 应用每个样式属性
                Object.entries(data.styles).forEach(([property, value]) => {
                  try {
                    element.style.setProperty(property, value, 'important')
                  } catch (err) {
                    console.warn(`设置样式失败: ${property}=${value}`, err)
                  }
                })
              })
            }

            // 处理子层级
            if (data.children && data.children.size > 0) {
              elements.forEach(element => {
                if (element) {
                  this.applyChildStylesOptimized(element, data.children, currentSelector)
                }
              })
            }
          } catch (err) {
            console.warn(`处理选择器失败: ${currentSelector}`, err)
            continue
          }
        }
      } catch (err) {}
    }
  },
  beforeMount () {
    if (this.useOssForImg) {
      this.uploadParams.resUploadMode = 'oss'
    }
  },
  mounted () {
    this.$nextTick(() => {
      if (this.allSlotSum === 0) this.$emit('slotsConfigEnded')
      // 挂载后注册快捷键
      this.registerShortcutsIfNeeded()
    })
  },
}

</script>

<style scoped lang="less">
.inputsDiv {
  display: flex;
  justify-content: space-between;

  .inputsDivItem {
    display: flex;
    align-items: center;
    padding: 0 4px;
    white-space: nowrap;

    .inputsDivItemLabel {
      padding: 0 4px;
    }
  }
}

.tdNoBorder {
  border-left: 1px solid #000;
  border-right: 1px solid #000;
  padding: 8px;
}

.tdWithBorder {
  border: 1px solid #000;
  padding: 8px;
}

.tdWithNoTopBorder {
  border-top-style: none;
  border-left: 1px solid #000;
  border-right: 1px solid #000;
  border-bottom: 1px solid #000;
  padding: 8px;
}

.grid-content {
  border-radius: 4px;
  min-height: 36px;
  text-align: center;
  color: #fff;
  background-color: #606266;
}

.bg-purple {
  background: #9254de;
}

.bg-purple-light {
  background: #b37feb;
}

.flexItem {
  border-radius: 8px;
  height: 100%;
  :deep(.ant-card-body) {
    padding: 0 !important;
  }
}

</style>
