<template>
    <view>
        <!-- 统一表格容器，根据屏幕宽度自适应 -->
        <view class="table-container" :class="{ 'mobile-table': isMobile }">
            <uni-table :type="selectionType" :border="false" @selection-change="handleSelectionChange" emptyText="">
                <!-- 表头：根据设备类型显示不同的列 -->
                <uni-tr class="table-header">
                    <uni-th v-for="column in displayColumns" :key="column.prop" :align="column.align || 'center'"
                        :width="column.width || '200'" :class="[headerClass, { sortable: column.sortable }]"
                        :style="getHeaderStyle(column)" @click="column.sortable && handleSort(column)">
                        <view class="header-content">
                            {{ column.label }}
                            <view v-if="column.sortable" class="sort-icon">
                                <uni-icons :type="getSortIcon(column)" :size="14" color="#999" />
                            </view>
                        </view>
                    </uni-th>
                </uni-tr>


                <!-- 表格主体 -->
                <template v-for="(row, rowIndex) in tableData" :key="rowIndex">
                    <uni-tr>
                        <!-- 数据列：根据设备类型动态渲染 -->
                        <uni-td v-for="column in displayColumns" :key="column.prop" :align="column.align || 'center'"
                            :class="getCellClass(column, row)" :style="getCellStyle(column, row)"
                            @click="openRowDetail(row)">
                            <template v-if="column.slot">
                                <slot :name="column.slot" :row="row" :column="column" :index="rowIndex">
                                    {{ row[column.prop] }}
                                </slot>
                            </template>
                            <uni-tag v-else-if="column.type === 'tag'" :text="formatTagText(row[column.prop], column)"
                                :type="formatTagType(row[column.prop], column)" size="small" />
                            <view v-else-if="column.type === 'file'">
                                <cwg-file :path="row[column.prop]" />
                            </view>
                            <view v-else-if="column.type === 'note'">
                                <text>{{ getNoteText(row, locale, userStore) }}</text>
                            </view>
                            <view v-else-if="column.type === 'action'" class="action-wrapper">
                                <cwg-droplist v-if="getComputedMenuList(column.menuList, row).length > 0"
                                    :menuList="getComputedMenuList(column.menuList, row)" placement="bottom-end"
                                    @menuClick="(payload) => handleActionClick(payload, row)">
                                    <view class="action-trigger">
                                        <cwg-icon name="crm-ellipsis" :size="24" color="#000" />
                                    </view>
                                </cwg-droplist>
                            </view>
                            <template v-else-if="column.type === 'more'">
                                <cwg-icon v-if="isMobile" name="crm-chevron-down" class="crm-chevron-down" :size="16"
                                    color="#007" />
                            </template>

                            <template v-else>
                                {{ formatCellValue(row[column.prop], column, row) }}
                            </template>
                        </uni-td>
                    </uni-tr>
                    <!-- 桌面端展开行（仅当非移动端且行展开时显示） -->
                    <uni-tr v-if="!isMobile && expandedRows[rowIndex]" class="expand-row">
                        <uni-td :colspan="columnSpan" class="expand-cell">
                            <slot name="expand" :row="row" :rowIndex="rowIndex">
                                <view class="default-expand-content">
                                    <text class="no-content">暂无展开内容</text>
                                </view>
                            </slot>
                        </uni-td>
                    </uni-tr>
                </template>

                <!-- 总计行 -->
                <uni-tr v-if="showSummary && tableData.length !== 0" class="summary-row">
                    <uni-td v-for="(column, index) in displayColumns" :key="'summary-' + column.prop"
                        :align="column.align || 'center'" class="summary-cell"
                        :style="getCellStyle(column, currentSummaryData)">
                        <!-- 当有 summaryMethod 时，按照返回的数组直接渲染 -->
                        <template v-if="props.summaryMethod">
                            <text>{{ computedSummaryRow[index] !== undefined ? computedSummaryRow[index] : '' }}</text>
                        </template>
                        <template v-else>
                            <!-- 特定列的总计自定义插槽，例如 #summary-volume="{ row }" -->
                            <template v-if="$slots['summary-' + column.prop]">
                                <slot :name="'summary-' + column.prop" :row="currentSummaryData" :column="column"
                                    :index="index"></slot>
                            </template>
                            <!-- 如果没有特定插槽，尝试常规渲染 -->
                            <template v-else>
                                <template
                                    v-if="currentSummaryData && currentSummaryData[column.prop] !== undefined && currentSummaryData[column.prop] !== null">
                                    <!-- 如果有常规插槽，并且总计数据里有该字段的值，则复用常规插槽渲染 -->
                                    <slot v-if="column.slot" :name="column.slot" :row="currentSummaryData"
                                        :column="column" :index="index">
                                        {{ currentSummaryData[column.prop] }}
                                    </slot>
                                    <!-- 否则使用格式化函数 -->
                                    <text v-else>{{ formatCellValue(currentSummaryData[column.prop], column,
                                        currentSummaryData) }}</text>
                                </template>
                                <!-- 如果总计数据里没有该字段的值，第一列显示总计文本，其他留空 -->
                                <text v-else>{{ index === 0 ? summaryText : '' }}</text>
                            </template>
                        </template>
                    </uni-td>
                </uni-tr>
            </uni-table>
        </view>
        <view class="table-loading-mask">
            <uni-loading v-if="loading" />
        </view>
        <!-- 空状态 -->
        <view v-if="!loading && tableData.length === 0" style="width: 100%;">
            <cwg-empty-state />
        </view>
        <!-- 分页 -->
        <view class="pagination-container" v-if="showPagination && tableData.length > 0">
            <!-- <view class="pagination-info">
                <text>共 {{ pagination.total }} 条记录</text>
                <view v-if="showPageSize" class="page-size-select">
                    <text>每页显示</text>
                    <picker @change="handlePageSizeChange" :value="pageSizeIndex" :range="pageSizes">
                        <view class="page-size-value">{{ pagination.pageSize }}条/页</view>
                    </picker>
                </view>
            </view> -->
            <view class="pagination">
                <view class="page-item prev" :class="{ disabled: pagination.current === 1 }"
                    @click="handlePageChange('prev')">
                    <uni-icons type="arrowright" size="14" :color="pagination.current === 1 ? '#c0c4cc' : '#606266'"
                        class="arrow-left" />
                </view>

                <view class="page-numbers">
                    <view v-for="(page, index) in visiblePages" :key="index" class="page-number"
                        :class="{ active: pagination.current === page, ellipsis: page === '...' }"
                        @click="page !== '...' && handlePageChange(page)">
                        {{ page }}
                    </view>
                </view>

                <view class="page-item next" :class="{ disabled: pagination.current === pagination.pages }"
                    @click="handlePageChange('next')">
                    <uni-icons type="arrowright" size="14"
                        :color="pagination.current === pagination.pages ? '#c0c4cc' : '#606266'" />
                </view>
            </view>
        </view>
        <!-- 移动端详情弹窗 -->
        <!-- <cwg-detail-popup v-model:visible="detailVisible" title="详情" :items="detailItems" /> -->
        <cwg-detail-popup v-model:visible="detailVisible" title="详情" :row="detailRow" :columns="detailColumns">
            <template v-for="col in detailColumns" :key="col.prop" #[`cell-${col.prop}`]="{ row, column }">
                <view v-if="col.type === 'file'">
                    <cwg-file :path="row[column.prop]" />
                </view>
                <slot v-else-if="col.slot" :name="col.slot" :row="row" :column="column" :index="0" />
            </template>
        </cwg-detail-popup>
    </view>
</template>

<script setup>
import { ref, computed, watch, onMounted, onUnmounted, nextTick } from 'vue'
import { getNoteText } from '@/utils/noteHelper';
import useUserStore from "@/stores/use-user-store";
import { useI18n } from "vue-i18n";
const userStore = useUserStore();
const { locale } = useI18n();
const props = defineProps({
    /**
     * 表格列配置（columns 数组中每一项是一个列配置对象）
     * - prop: 字段名，对应 row[prop]，用于取值/排序/详情展示
     * - label: 表头显示文本（也会作为详情弹窗的 label）
     * - align: 对齐方式（'left' | 'center' | 'right'）
     * - width: 列宽（设置后该列固定宽度；未设置则自适应
     * - slot: 自定义渲染插槽名（<template #xxx="{ row, column, index }">），优先级最高
     * - formatter: ({ value, row }) => string | number，自定义格式化显示值（无 slot 时生效）
     * - sortable: 是否可排序（点击表头切换 asc/desc）
     * - headerStyle: 表头样式（对象），会合并到表头 style
     * - cellStyle: 单元格样式（对象或函数({ row, column }) => style）
     * - cellClass: 单元格 class（string 或函数({ row, column }) => string | string[]）
     * - isTabel: false 时不在表格中显示该列，但仍会在“详情弹窗”中显示
     * - type: 内置渲染类型
     * - 'tag': 使用 uni-tag 渲染，搭配 tagMap/tagTypeMap
     * - 'file': 使用 cwg-file 渲染
     * - 'more': 展示“更多”图标（用于移动端点击查看详情等）
     * - 'date': 日期格式化（搭配 dateFormat）
     * - 'action': 操作按钮
     * - tagMap: 标签映射对象
     * - tagTypeMap: 标签类型映射对象
     * - dateFormat: 日期格式
    *  */
    columns: { type: Array, required: true, default: () => [] },
    // 移动端配置
    mobilePrimaryCount: { type: Number, default: 3 },
    // 参数如columns
    mobilePrimaryFields: { type: Array, default: () => [] },
    // API 请求函数
    api: { type: Function },
    // 查询参数
    queryParams: { type: Object, default: () => ({}) },
    // 是否立即加载
    immediate: { type: Boolean, default: true },
    // 选择类型：'selection' | null
    selectionType: { type: String, default: null },
    // 是否显示每页条数选择
    showPageSize: { type: Boolean, default: true },
    // 是否显示分页
    showPagination: { type: Boolean, default: true },
    isViewDetail: { type: Boolean, default: true },
    // 每页条数选项
    pageSizes: { type: Array, default: () => [2, 4, 6, 8, 10, 20, 30, 50, 100] },
    // 默认每页条数
    defaultPageSize: { type: Number, default: 10 },
    // 表头样式自定义
    headerBackground: { type: String, default: '#fff' },
    headerColor: { type: String, default: 'var(--color-slate-800)' },
    headerFontSize: { type: [String, Number], default: '28rpx' },
    headerFontWeight: { type: [String, Number], default: 600 },
    headerHeight: { type: [String, Number], default: '64rpx' },
    headerClass: { type: [String, Array], default: '' },
    headerStyle: { type: Object, default: () => ({}) },
    stickyHeader: { type: Boolean, default: true },
    stickyOffset: { type: [String, Number], default: '0' },
    // 是否跳转页面
    isPages: { type: Boolean, default: false },
    // 自定义详情的时候，手机端才跳转，pc端不跳转
    pagesToDetail: { type: Boolean, default: false },
    // 是否显示总计行
    showSummary: { type: Boolean, default: false },
    // 自定义总计数据，若不传则尝试使用 api 响应中的 res.sum
    summaryData: { type: Object, default: () => null },
    // 传入的静态数据，有此数据时则不发起 api 请求
    data: { type: Array, default: () => null },
    // 自定义的合计计算方法，如果配置了，则使用该方法计算总计数据
    summaryMethod: { type: Function, default: null },
    // 总计行第一列的默认文本
    summaryText: { type: String, default: '总计' },
})
const emit = defineEmits([
    'selection-change',
    'action-click',
    'page-change',
    'load-success',
    'load-error',
    'sort-change',
    'go-pages'
])

// ========== 响应式状态 ==========
const tableData = ref([])
const selectedItems = ref([])
const detailVisible = ref(false)
const detailItems = ref([])
// 替换原来的 detailItems 相关定义
const detailRow = ref(null)
const detailColumns = ref([])
const pagination = ref({
    current: 1,
    pageSize: props.defaultPageSize,
    total: 0,
    pages: 0
})
const loading = ref(false)
const expandedRows = ref({})
const internalSummaryData = ref(null)

const currentSummaryData = computed(() => {
    if (props.summaryData && Object.keys(props.summaryData).length > 0) return props.summaryData
    return internalSummaryData.value
})

const computedSummaryRow = computed(() => {
    if (props.showSummary && props.summaryMethod && typeof props.summaryMethod === 'function') {
        const result = props.summaryMethod({
            columns: displayColumns.value,
            data: tableData.value,
            summaryData: currentSummaryData.value
        });
        return Array.isArray(result) ? result : [];
    }
    return [];
});

// 移动端检测
const isMobile = ref(false)
// 排序状态
const sortState = ref({ prop: '', order: '' }) // order: 'asc' | 'desc' | ''

// action 列的状态处理
const getComputedMenuList = (menuList, row) => {
    if (!menuList) return []
    return menuList.filter(item => {
        if (typeof item.show === 'function') {
            return item.show(row) !== false
        }
        return item.show !== false
    })
}

const handleActionClick = (payload, row) => {
    const { value } = payload
    // 如果你在 menuList 中定义了 btnClick，则直接调用并传入当前行数据
    if (value && typeof value.btnClick === 'function') {
        value.btnClick(row)
    }
}

// ========== 计算属性 ==========
// 显示的列（根据设备类型）
const displayColumns = computed(() => {
    const filterForTable = (cols) => (cols || []).filter((c) => c && c.isTabel !== false)

    const normalizeColumns = (cols) => {
        if (!Array.isArray(cols)) return []
        if (cols.length === 0) return []
        const first = cols[0]
        if (typeof first === 'string') {
            return cols
                .map((prop) => props.columns.find((c) => c && c.prop === prop))
                .filter(Boolean)
        }
        return cols
    }

    if (!isMobile.value) return filterForTable(normalizeColumns(props.columns))

    if (props.mobilePrimaryFields && props.mobilePrimaryFields.length) {
        return filterForTable(normalizeColumns(props.mobilePrimaryFields))
    }
    return filterForTable(normalizeColumns(props.columns.slice(0, props.mobilePrimaryCount)))
})

// 列跨度（用于展开行）
const columnSpan = computed(() => {
    let span = displayColumns.value.length
    if (props.showOperation) span += 1
    return span
})

// 每页条数索引
const pageSizeIndex = computed(() => {
    return props.pageSizes.indexOf(pagination.value.pageSize)
})

// 可见页码
const visiblePages = computed(() => {
    const totalPages = pagination.value.pages
    const currentPage = pagination.value.current
    const maxVisible = 4 // 显示的页码数量（包括第一页和最后一页）

    if (totalPages <= maxVisible) {
        return Array.from({ length: totalPages }, (_, i) => i + 1)
    }

    let pages = []

    if (currentPage <= 2) {
        // 当前页靠前：[1, 2, '...', 最后一页]
        pages = [1, 2, '...', totalPages]
    } else if (currentPage >= totalPages - 1) {
        // 当前页靠后：[1, '...', 倒数第二页, 最后一页]
        pages = [1, '...', totalPages - 1, totalPages]
    } else {
        // 当前页在中间：由于只显示4个，去掉后面的...直接紧凑展示：[1, '...', 当前页, 最后一页]
        // 或者：[1, 当前页, '...', 最后一页] 以确保当前页能点到
        pages = [1, '...', currentPage, totalPages]
    }

    return pages
})
// ========== 工具函数 ==========
// 获取表头样式
const getHeaderStyle = (column) => {
    const baseStyle = {
        backgroundColor: props.headerBackground,
        color: props.headerColor,
        fontSize: typeof props.headerFontSize === 'number' ? props.headerFontSize + 'rpx' : props.headerFontSize,
        fontWeight: props.headerFontWeight,
        height: typeof props.headerHeight === 'number' ? props.headerHeight + 'rpx' : props.headerHeight,
        lineHeight: typeof props.headerHeight === 'number' ? props.headerHeight + 'rpx' : props.headerHeight,
        ...props.headerStyle
    }
    if (props.stickyHeader) {
        baseStyle.position = 'sticky'
        baseStyle.top = props.stickyOffset
        baseStyle.zIndex = 100
    }
    if (column.width) {
        const w = typeof column.width === 'number' ? column.width + 'px' : column.width
        baseStyle.width = w
        baseStyle.minWidth = w
        baseStyle.maxWidth = w
    }
    if (column.headerStyle) {
        Object.assign(baseStyle, column.headerStyle)
    }
    return baseStyle
}

// 获取单元格样式
const getCellStyle = (column, row) => {
    const style = {}
    if (column.width) {
        const w = typeof column.width === 'number' ? column.width + 'px' : column.width
        style.width = w
        style.minWidth = w
        style.maxWidth = w
        style.wordBreak = 'break-all'

        // 如果是自定义插槽，允许内容换行或由内部元素自己控制溢出，不强制隐藏
        if (column.slot) {
            style.whiteSpace = 'normal'
            style.overflow = 'visible'
            style.textOverflow = 'clip'
        } else {
            style.whiteSpace = 'nowrap'
            style.overflow = 'hidden'
            style.textOverflow = 'ellipsis'
        }
    } else {
        // 如果没有定宽，保证默认情况下单元格内容不会被直接 hidden 切掉下拉弹窗
        if (column.slot) {
            style.overflow = 'visible'
        }
    }
    if (column.cellStyle) {
        if (typeof column.cellStyle === 'function') {
            Object.assign(style, column.cellStyle({ row, column }))
        } else {
            Object.assign(style, column.cellStyle)
        }
    }
    return style
}

// 获取单元格类名
const getCellClass = (column, row) => {
    const classes = []
    if (column.cellClass) {
        if (typeof column.cellClass === 'function') {
            const result = column.cellClass({ row, column })
            if (result) {
                if (Array.isArray(result)) {
                    classes.push(...result)
                } else {
                    classes.push(result)
                }
            }
        } else {
            classes.push(column.cellClass)
        }
    }
    return classes.join(' ')
}

// 格式化单元格值
const formatCellValue = (value, column, row) => {
    if (column.formatter) {
        return column.formatter({ value, row })
    }
    if (column.type === 'date' && value) {
        return formatDate(value, column.dateFormat || 'YYYY-MM-DD HH:mm:ss')
    }
    if (column.type === 'tag' && value) {
        return formatTagText(value, row)
    }
    if (value === null || value === undefined) {
        return '-'
    }
    return value
}

// 格式化标签文本
const formatTagText = (value, column) => {
    if (column.tagMap && column.tagMap[value]) {
        return column.tagMap[value]
    }
    return value || '-'
}

// 格式化标签类型
const formatTagType = (value, column) => {
    if (column.tagTypeMap && column.tagTypeMap[value]) {
        return column.tagTypeMap[value]
    }
    return 'default'
}

// 格式化日期
const formatDate = (date, format) => {
    if (!date) return '-'
    const d = new Date(date)
    const year = d.getFullYear()
    const month = String(d.getMonth() + 1).padStart(2, '0')
    const day = String(d.getDate()).padStart(2, '0')
    const hour = String(d.getHours()).padStart(2, '0')
    const minute = String(d.getMinutes()).padStart(2, '0')
    const second = String(d.getSeconds()).padStart(2, '0')

    return format
        .replace('YYYY', year)
        .replace('MM', month)
        .replace('DD', day)
        .replace('HH', hour)
        .replace('mm', minute)
        .replace('ss', second)
}

// 排序图标
const getSortIcon = (column) => {
    if (sortState.value.prop !== column.prop) return 'arrow-up'
    return sortState.value.order === 'asc' ? 'arrow-up' : 'arrow-down'
}

// 处理排序
const handleSort = (column) => {
    if (!column.sortable) return
    let newOrder = ''
    if (sortState.value.prop === column.prop) {
        if (sortState.value.order === '') newOrder = 'asc'
        else if (sortState.value.order === 'asc') newOrder = 'desc'
        else newOrder = ''
    } else {
        newOrder = 'asc'
    }
    sortState.value = { prop: newOrder ? column.prop : '', order: newOrder }
    emit('sort-change', { prop: sortState.value.prop, order: sortState.value.order })
    // refreshTable()
}
// 展开行切换
const toggleRowExpand = (rowIndex) => {
    const key = rowIndex
    if (expandedRows.value[key]) {
        expandedRows.value[key] = false
    } else {
        expandedRows.value = {}
        expandedRows.value[key] = true
    }
    emit('expand-change', { rowIndex, expanded: expandedRows.value[key] })
}
// 打开详情弹窗（移动端使用）
// 修改 openRowDetail
const openRowDetail = (row) => {
    if (props.isPages) {
        emit('go-pages', row)
    } else {
        if (props.pagesToDetail) {
            emit('go-pages', row)
        } else if (isMobile.value) {
            // 保存当前行和需要显示的列（有 prop 且有 label） pc 详情不展示操作按钮
            detailRow.value = { ...row, note: getNoteText(row, locale.value, userStore) }
            detailColumns.value = !isMobile.value ? props.columns.filter(col => col && col.prop && col.label && col.type !== 'action') : props.columns.filter(col => col && col.prop && col.label)
            detailVisible.value = true
        }
    }
}
const setDetailVisible = (visible) => {
    detailVisible.value = visible
}

// ========== 数据加载 ==========
const loadData = async () => {
    if (props.data) {
        tableData.value = props.data
        if (props.summaryData) {
            internalSummaryData.value = props.summaryData
        }
        return
    }
    tableData.value = []
    if (loading.value) return
    loading.value = true
    try {
        const applyPaginationFromRes = (res) => {
            const page = res && res.page
            if (!page) return false
            if (typeof page.current === 'number') pagination.value.current = page.current
            if (typeof page.row === 'number') pagination.value.pageSize = page.row
            if (typeof page.rowTotal === 'number') pagination.value.total = page.rowTotal
            if (typeof page.pageTotal === 'number') pagination.value.pages = page.pageTotal
            else if (typeof pagination.value.total === 'number' && typeof pagination.value.pageSize === 'number') {
                pagination.value.pages = Math.ceil(pagination.value.total / pagination.value.pageSize)
            }
            return true
        }
        // 👇 修复后：使用解构获取最新的 queryParams，杜绝延迟
        const query = { ...props.queryParams };

        let startDate = "";
        let endDate = "";

        // 处理日期范围（用解构后的 query，绝对最新）
        if (!query.date || query.date.length === 0) {
            startDate = "";
            endDate = "";
        } else {
            startDate = query.date[0] || "";
            endDate = query.date[1] || "";
        }

        // 组装请求参数
        const params = {
            page: {
                current: pagination.value.current,
                row: pagination.value.pageSize
            },
            ...query,        // 用解构后的最新 query
            startDate,
            endDate
        };

        // 添加排序参数
        if (sortState.value.prop && sortState.value.order) {
            params.sort = { field: sortState.value.prop, order: sortState.value.order }
        }
        const res = await props.api(params)
        if (res.code === 200 || res.code === 0 || res.code === 10000) {
            if (res.sum) {
                internalSummaryData.value = res.sum
            } else {
                internalSummaryData.value = null
            }
            const data = res.data || res
            const hasPage = applyPaginationFromRes(res)
            if (Array.isArray(data)) {
                tableData.value = data
                if (!hasPage) {
                    pagination.value.total = data.length
                    pagination.value.pages = 1
                }
            } else if (data.list || data.records) {
                tableData.value = data.list || data.records
                if (!hasPage) {
                    pagination.value.total = data.total || data.list?.length || 0
                    pagination.value.pages = data.pages || Math.ceil(pagination.value.total / pagination.value.pageSize)
                }
            } else {
                tableData.value = []
            }
            emit('load-success', res)
        } else {
            throw new Error(res.message || '加载失败')
        }
    } catch (error) {
        console.error('表格数据加载失败:', error)
        uni.showToast({
            title: error.message || '加载失败',
            icon: 'none'
        })
        emit('load-error', error)
    } finally {
        loading.value = false
        pageLoading.value = false
    }
}
// 刷新表格
const refreshTable = () => {
    pagination.value.current = 1
    loadData()
}
const reload = () => {
    loadData()
}
const pageLoading = ref(false)
// 分页变化
const handlePageChange = (page) => {
    if (pageLoading.value) return
    pageLoading.value = true
    if (page === 'prev') {
        if (pagination.value.current > 1) pagination.value.current--
        else return
    } else if (page === 'next') {
        if (pagination.value.current < pagination.value.pages) pagination.value.current++
        else return
    } else {
        pagination.value.current = page
    }
    loadData()
    emit('page-change', pagination.value)
}
// 每页条数变化
const handlePageSizeChange = (e) => {
    const size = props.pageSizes[e.detail.value]
    pagination.value.pageSize = size
    pagination.value.current = 1
    loadData()
}
// 选择变化
const handleSelectionChange = (e) => {
    selectedItems.value = e.detail.value
    emit('selection-change', selectedItems.value)
}
// 获取选中项
const getSelectedItems = () => selectedItems.value
const clearSelection = () => { selectedItems.value = [] }
// ========== 移动端检测 ==========
const checkIsMobile = () => {
    // 适配 uni-app 环境
    // #ifdef H5
    const width = window.innerWidth
    isMobile.value = width < 991
    // #endif
    // #ifndef H5
    const systemInfo = uni.getSystemInfoSync()
    isMobile.value = systemInfo.windowWidth < 991
    // #endif
}
// 监听窗口大小变化（仅 H5）
// #ifdef H5
const handleResize = () => {
    checkIsMobile()
}
// #endif
// ========== 监听参数变化 ==========
watch(() => props.data, (newData) => {
    if (newData) {
        tableData.value = newData
    }
}, { deep: true, immediate: true })

watch(() => props.summaryData, (newSum) => {
    if (props.data && newSum) {
        internalSummaryData.value = newSum
    }
}, { deep: true, immediate: true })

watch(() => props.queryParams, () => {
    nextTick(() => {
        // refreshTable()
    })
}, { deep: true })
watch(() => props.api, () => {
    nextTick(() => {
        refreshTable()
    })
}, { deep: true })
// ========== 生命周期 ==========
onMounted(() => {
    checkIsMobile()
    // #ifdef H5
    window.addEventListener('resize', handleResize)
    // #endif
    if (props.immediate) {
        loadData()
    }
})
onUnmounted(() => {
    // #ifdef H5
    window.removeEventListener('resize', handleResize)
    // #endif
})
// 暴露方法
defineExpose({
    refreshTable,
    reload,
    getSelectedItems,
    clearSelection,
    loadData,
    tableData,
    toggleRowExpand,
    pagination,
    setDetailVisible
})
</script>

<style scoped lang="scss">
@import "@/uni.scss";

.table-container {
    width: 100%;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    margin-top: px2rpx(20);
    max-height: calc(100vh - 209px);
    color: var(--color-slate-800);

    .action-wrapper {
        display: flex;
        justify-content: center;
        align-items: center;

        .action-trigger {
            display: flex;
            justify-content: center;
            align-items: center;
            cursor: pointer;
            padding: px2rpx(4);
            border-radius: px2rpx(4);
            transition: background-color 0.2s;

            &:hover {
                background-color: rgba(0, 0, 0, 0.05);
            }
        }
    }

    .table-loading-mask {
        width: 100%;
        height: 100%;
        // margin: 0 auto;
        display: flex;
        align-items: center;
        justify-content: center;
    }

    :deep(.uni-table-scroll) {
        width: 100%;
        max-height: calc(100vh - 375px);
        //min-height: 300px;
        overflow-y: auto;
        overflow-x: auto;

        /* 强制显示滚动条并美化 */
        &::-webkit-scrollbar {
            width: 4px !important;
            height: 4px !important;
            display: block !important;
            /* 强制在某些webkit浏览器中显示 */
            background-color: #ccc !important;
        }

        &::-webkit-scrollbar-track {
            background-color: #ccc;
            border-radius: 4px;
        }

        &::-webkit-scrollbar-thumb {
            background-color:#ccc;
            border-radius: 4px;

            &:hover {
                background-color: #ccc;
            }
        }
    }

    :deep(.uni-table) {
        border-radius: 8px;
        box-shadow: 0 1px 4px rgba(0, 0, 0, 0.02);

        .uni-table-th {
            position: sticky;
            top: 0;
            z-index: 100;
            transition: all 0.3s;
            background-color: rgba(var(--bs-danger-rgb), var(--bs-bg-opacity)) !important;
            border-bottom: 1px solid var(--bs-light-bg-subtle) !important;
            color: rgb(var(--bs-white-rgb)) !important;

            .header-content {
                display: flex;
                align-items: center;
                justify-content: center;
                gap: 4px;

                .sort-icon {
                    display: inline-flex;
                    cursor: pointer;
                }
            }

            &.sortable {
                cursor: pointer;

                &:hover .sort-icon .uni-icons {
                    color: var(--color-primary) !important;
                }
            }

            &::after {
                display: none;
            }
        }

        .uni-table-tr {
            transition: background-color 0.2s ease;
            border-bottom: 1px solid var(--bs-light-bg-subtle) !important;
            color: var(--bs-emphasis-color) !important;

            // 奇数行背景颜色
            &:nth-child(odd) {
                background-color: var(--bs-light-bg-subtle);
            }

            // 偶数行背景颜色
            &:nth-child(even) {
                background-color: var(--bs-body-bg);
            }

            &:hover {
                background-color: var(--bs-light-bg-subtle) !important;
            }

            &:last-child {
                border-bottom: none !important;
            }
        }

        .summary-row {
            background-color: var(--bs-light-bg-subtle);
            font-weight: 600;

            .uni-table-td {
                border-top: 1px solid var(--bs-light-bg-subtle) !important;
                position: sticky;
                bottom: 0;
                z-index: 99;
                background-color: var(--bs-light-bg-subtle);
            }
        }

        .uni-table-td {
            padding: px2rpx(16) px2rpx(5);
            color: var(--bs-emphasis-color) !important;
            border-bottom: 1px solid var(--bs-light-bg-subtle) !important;
            box-sizing: border-box;
            vertical-align: middle;
            font-size: 14px;
            white-space: nowrap;
        }

        .uni-table-th {
            padding: px2rpx(6) px2rpx(5);
            box-sizing: border-box;
            vertical-align: middle;
            font-size: 14px;
            white-space: nowrap;
            word-break: keep-all;
        }


        .action-wrapper {
            max-width: 180px;
            white-space: normal;
        }

        .action-list {
            display: flex;
            flex-wrap: wrap;
            gap: 6px 5px;
            align-items: center;
        }

        .action-btn {
            color: var(--color-primary);
            text-decoration: underline;
            cursor: pointer;
            font-size: px2rpx(12);
            white-space: nowrap;
        }

        .action-toggle-btn {
            color: #909399;
            cursor: pointer;
            font-size: px2rpx(12);
            white-space: nowrap;
        }

        .expand-cell {
            padding: 0 !important;
        }
    }
}

.crm-chevron-down {
    transform: rotate(-90deg);
    cursor: pointer;
}

.mobile-table {
    :deep(.uni-table) {
        min-width: 0 !important;
    }
}

.detail-btn-mobile {
    background-color: #f0f0f0;
    color: var(--bs-heading-color);
}

/* 分页样式 */
.pagination-container {
    margin: px2rpx(20) 0;
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: px2rpx(20);
    position: relative;
    z-index: 10;
    background-color: transparent;

    .pagination {
        display: flex;
        align-items: center;
        //padding: px2rpx(10);
    }

    .page-item {
        display: flex;
        align-items: center;
        justify-content: center;
        padding: 0 px2rpx(12);
        min-width: px2rpx(32);
        height: px2rpx(30);
        background-color: rgba(var(--bs-body-bg-rgb), var(--bs-bg-opacity)) !important;
        border-radius: px2rpx(4);
        font-size: px2rpx(14);
        color: #606266;
        cursor: pointer;
        transition: all 0.3s;
        margin: 0 px2rpx(6);

        &:not(.disabled):hover {
            color: #cf1322;
        }

        &.disabled {
            opacity: 0.5;
            cursor: not-allowed;
            pointer-events: none;
            color: #c0c4cc;
        }
    }

    .page-numbers {
        display: flex;
        flex: 1;
        gap: px2rpx(8);
    }

    .arrow-left {
        transform: rotate(180deg);
    }

    .page-number {
        display: flex;
        align-items: center;
        justify-content: center;
        min-width: px2rpx(20);
        height: px2rpx(26);
        padding: 0 px2rpx(4);
        background-color: rgba(var(--bs-body-bg-rgb), var(--bs-bg-opacity)) !important;
        border-radius: px2rpx(4);
        font-size: px2rpx(12);
        color: #606266;
        cursor: pointer;
        transition: all 0.3s;
        font-weight: 500;

        &.ellipsis {
            cursor: default;
            background: transparent;
            color: #c0c4cc;
            font-weight: bold;
            min-width: px2rpx(24);
        }

        &:not(.ellipsis):hover {
            color: #cf1322;
        }

        &.active {
            background-color: #cf1322;
            color: var(--bs-emphasis-color);
            border-color: #cf1322;

            &:hover {
                color: var(--bs-emphasis-color);
            }
        }
    }

    .pagination-info {
        display: flex;
        align-items: center;
        gap: px2rpx(30);
        font-size: px2rpx(16);
        color: #909399;
    }

    .page-size-select {
        display: flex;
        align-items: center;
        gap: px2rpx(10);
    }

    .page-size-value {
        padding: px2rpx(6) px2rpx(20);
        border: 1px solid #dcdfe6;
        border-radius: px2rpx(8);
        color: #606266;
    }
}

@media screen and (max-width: 768px) {
    .pagination {
        flex-wrap: nowrap;
        justify-content: center;
        width: 100%;
        overflow-x: auto;
        -webkit-overflow-scrolling: touch;

        &::-webkit-scrollbar {
            display: none;
        }
    }

    .page-numbers {
        flex: none;
        gap: px2rpx(4);
    }

    .page-item {
        padding: 0 px2rpx(8);
        min-width: px2rpx(28);
        margin: 0 px2rpx(2);
    }

    .page-number {
        min-width: px2rpx(28);
        padding: 0 px2rpx(4);
        font-size: px2rpx(12);

        &.ellipsis {
            min-width: px2rpx(16);
            padding: 0;
        }
    }

    .pagination-info {
        flex-direction: column;
        gap: px2rpx(10);
    }
}
</style>
