
import { getProductById } from '../../utils/productService'
import { getMachineInfo, getPayTypes,getShopMachineList,addGoodsV2 } from '../../api/products'
import { truncateAmountByCoin, truncateTo6 } from '../../utils/amount'
import { getGoodsListV2 } from '../../api/shoppingCart'

export default {
    name: 'ProductDetail',
    data() {
        return {
            product: null,
            loading: false,
            // 默认展开的行keys
            expandedRowKeys: [],
            selectedMap: {},
            // 新接口：单层矿机列表 & 支付方式
            machineList: [],
            paymentMethodList: [],
            // 筛选状态
            selectedPayKey: null,
            filters: {
                chain: '',
                coin: '',
                minPrice: null,
                maxPrice: null,
                minPower: null,
                maxPower: null,
                minPowerDissipation: null,
                maxPowerDissipation: null,
                unit: 'GH/S'
            },
            // 实际算力单位选项
            powerUnitOptions: ['KH/S', 'MH/S', 'GH/S', 'TH/S', 'PH/S'],
            // 排序状态：true 升序，false 降序
            sortStates: {
                priceSort: true,
                powerSort: true,
                powerDissipationSort: true
            },
            // 当前激活的排序字段（仅当用户点击后才会传参）
            activeSortField: '',
            // 首次进入时是否已按价格币种设置过支付方式筛选默认值
            payFilterDefaultApplied: false,
            params: {
                id: "",
                pageNum: 1,
                pageSize: 10,


            },
            confirmAddDialog: {
                visible: false,
                items: []
            },
            // 购物车中已存在的当前商品机器集合：id 与 user|miner 组合键
            cartMachineIdSet: new Set(),
            cartCompositeKeySet: new Set(),
            cartLoaded: false,
            machinesLoaded: false,
            /**
             * 可展开的产品系列数据
             * 每个系列(group)包含多个可选条目(variants)
             */
            productListData: [
                // {
                //     id: 'grp-1',
                //     group: 'A系列',
                //     summary: {
                //         theoryPower: '56T',
                //         computingPower: '54T',
                //         powerDissipation: '3200W',
                //         algorithm: 'power',
                //         type: 'A-Pro',
                //         count: 3,
                //         price: '¥1000+'
                //     },
                //     variants: [
                //         { id: 'A-1', model: 'A1', theoryPower: '14T', computingPower: '13.5T', powerDissipation: '780W', algorithm: 'power', stock: 50, price: 999, quantity: 1 },
                //         { id: 'A-2', model: 'A2', theoryPower: '18T', computingPower: '17.2T', powerDissipation: '900W', algorithm: 'power', stock: 40, price: 1299, quantity: 1 },
                //         { id: 'A-3', model: 'A3', theoryPower: '24T', computingPower: '23.1T', powerDissipation: '1520W', algorithm: 'power', stock: 30, price: 1699, quantity: 1 }
                //     ]
                // },
                // {
                //     id: 'grp-2',
                //     group: 'B系列',
                //     summary: {
                //         theoryPower: '72T',
                //         computingPower: '70T',
                //         powerDissipation: '4100W',
                //         algorithm: 'power',
                //         type: 'B-Max',
                //         count: 2,
                //         price: '¥2000+'
                //     },
                //     variants: [
                //         { id: 'B-1', model: 'B1', theoryPower: '32T', computingPower: '31.2T', powerDissipation: '1800W', algorithm: 'power', stock: 28, price: 2199, quantity: 1 },
                //         { id: 'B-2', model: 'B2', theoryPower: '40T', computingPower: '38.8T', powerDissipation: '2300W', algorithm: 'power', stock: 18, price: 2699, quantity: 1 }
                //     ]
                // }
            ],
            tableData: [
                // {
                //     theoryPower: "55656",//理论算力
                //     computingPower: "44545",//实际算力
                //     powerDissipation: "5565",//功耗
                //     algorithm: "power",//算法
                //     type: "型号1",//矿机型号
                //     number:2001,       
                //     cost:"1000",//价格            
                // },
                // {
                //     theoryPower: "55656",//理论算力
                //     computingPower: "44545",//实际算力
                //     powerDissipation: "5565",//功耗
                //     algorithm: "power",//算法
                //     type: "型号1",//矿机型号
                //     number:2001,       
                //     cost:"1000",//价格            
                // },
                // {
                //     theoryPower: "55656",//理论算力
                //     computingPower: "44545",//实际算力
                //     powerDissipation: "5565",//功耗
                //     algorithm: "power",//算法
                //     type: "型号1",//矿机型号
                //     number:2001,       
                //     cost:"1000",//价格            
                // },
                // {
                //     theoryPower: "55656",//理论算力
                //     computingPower: "44545",//实际算力
                //     powerDissipation: "5565",//功耗
                //     algorithm: "power",//算法
                //     type: "型号1",//矿机型号
                //     number:2001,       
                //     cost:"1000",//价格            
                // },

            ],
            productDetailLoading: false,
            pageSizes: [10, 20, 50],
            currentPage: 1,
            total: 0,
            // 动态列表（模拟渲染）
            dynamicMeta: {},
            dynamicColumns: [],
            dynamicRows: [],
            dynamicSearch: {
                visible: false,
                keyword: ''
            },
            // 矿机种类：0-ASIC，1-GPU（默认GPU）
            machineType: 1,
          

        }
    },
    mounted() {
      // 读取用户上次选择的矿机种类（0: ASIC, 1: GPU）
      try{
        const savedType = Number(window && window.localStorage ? window.localStorage.getItem('pl_machineType') : NaN)
        if (savedType === 0 || savedType === 1) {
          this.machineType = savedType
        }
      }catch(e){/* noop */}
      // 不再使用本地模拟数据，动态表格完全依赖后端返回的 columns/rows
        // 仅当路由携带 shopId 时，才发起店铺商品请求
        const routeShopId =
            (this.$route && this.$route.params && (this.$route.params.shopId || this.$route.params.id)) ||
            (this.$route && this.$route.query && this.$route.query.shopId)
        if (routeShopId) {
            this.params.id = routeShopId
            this.product = true
            this.fetchGetMachineInfo(this.buildQueryParams())
            this.fetchPayTypes()
        } else {
            this.$message.warning('缺少店铺ID（shopId），无法加载商品列表')
            this.product = false
        }
    },
    methods: {
        // 动态表格单元格格式化（金额/算力/天数/文本）- 统一最多显示6位小数，hover展示完整
        formatDynamicCell(row, col) {
            try{
                let val = row[col.key]
                if (val === null || val === undefined || val === '') return { text: '—', full: '—', truncated: false }
                if (col.type === 'amount') {
                    // 价格列：单位取 priceList 里的 coin；默认取第一条；选择支付方式后按选择展示
                    if (col.key === 'price') {
                        if (Array.isArray(row.priceList) && row.priceList.length) {
                            const pv = this.getDisplayPrice(row)
                            const pc = this.getDisplayPriceCoin(row)
                            if (pv !== null && pv !== undefined) val = pv
                            const nPrice = val
                            const t = truncateTo6(nPrice)
                            const coinUnit = (pc || '').toString().toUpperCase()
                            return {
                                text: coinUnit ? `${t.text} ${coinUnit}` : t.text,
                                full: coinUnit ? `${t.full} ${coinUnit}` : t.full,
                                truncated: t.truncated
                            }
                        }
                        // 无 priceList：仅展示数值，不附加任何单位
                        const t = truncateTo6(val)
                        return { text: t.text, full: t.full, truncated: t.truncated }
                    }
                    // 列级优先：若列声明 currency=USDT，则固定展示为 "xx.xx USDT"
                    const colCurrency = (col.currency || '').toString().toUpperCase()
                    if (colCurrency === 'USDT') {
                        const t = truncateTo6(val)
                        return { text: `${t.text} USDT`, full: `${t.full} USDT`, truncated: t.truncated }
                    }
                    // 兜底：不再使用 meta 的货币符号，直接返回数值
                    const t = truncateTo6(val)
                    return { text: t.text, full: t.full, truncated: t.truncated }
                }
                if (col.type === 'hashrate') {
                    // 接口已返回带单位的内容，直接返回字符串值，不拼接单位
                    const s = String(val || '')
                    return { text: s, full: s, truncated: false }
                }
                if (col.type === 'days') {
                    const n = Number(val)
                    if (!Number.isFinite(n)) return { text: String(val), full: String(val), truncated: false }
                    const s = `${Math.floor(n)} 天`
                    return { text: s, full: s, truncated: false }
                }
                const s = String(val)
                return { text: s, full: s, truncated: false }
            }catch(e){ return { text: '—', full: '—', truncated: false } }
        },
        /**
         * 如果存在 priceList，则用第一条的 chain|coin 作为默认筛选值，
         * 使“支付方式筛选”与价格列默认展示一致
         */
        ensureDefaultPayFilterFromPrices() {
            try{
                if (this.payFilterDefaultApplied) return
                const rows = Array.isArray(this.dynamicRows) ? this.dynamicRows : []
                const firstWithPriceList = rows.find(r => Array.isArray(r && r.priceList) && r.priceList.length)
                if (!firstWithPriceList) return
                const first = firstWithPriceList.priceList[0]
                const chain = String(first && first.chain || '').trim()
                const coin = String(first && first.coin || '').trim()
                if (!chain && !coin) return
                this.selectedPayKey = `${chain}|${coin}`
                this.filters.chain = chain
                this.filters.coin = coin
                this.payFilterDefaultApplied = true
            }catch(e){ /* noop */ }
        },
        /**
         * 获取行在当前支付方式下的展示价格
         * 优先匹配 selectedPayKey（chain|coin），否则回退 priceList[0]；再否则回退 row.price
         */
        getDisplayPrice(row){
            try{
                const list = Array.isArray(row && row.priceList) ? row.priceList : []
                if (!list.length) return row && row.price
                const key = this.selectedPayKey
                if (key) {
                    const [chainRaw, coinRaw] = String(key).split('|')
                    const chain = String(chainRaw || '').toUpperCase().trim()
                    const coin = String(coinRaw || '').toUpperCase().trim()
                    const hit = list.find(it =>
                        String(it && it.chain).toUpperCase().trim() === chain &&
                        String(it && it.coin).toUpperCase().trim() === coin
                    )
                    if (hit && hit.price !== undefined && hit.price !== null) return hit.price
                }
                const first = list[0]
                if (first && first.price !== undefined && first.price !== null) return first.price
                return row && row.price
            }catch(e){ return row && row.price }
        },
        /**
         * 获取行在当前支付方式下价格的币种（coin）
         */
        getDisplayPriceCoin(row){
            try{
                const list = Array.isArray(row && row.priceList) ? row.priceList : []
                if (!list.length) return ''
                const key = this.selectedPayKey
                if (key) {
                    const [chainRaw, coinRaw] = String(key).split('|')
                    const chain = String(chainRaw || '').toUpperCase().trim()
                    const coin = String(coinRaw || '').toUpperCase().trim()
                    const hit = list.find(it =>
                        String(it && it.chain).toUpperCase().trim() === chain &&
                        String(it && it.coin).toUpperCase().trim() === coin
                    )
                    if (hit && hit.coin) return String(hit.coin)
                }
                const first = list[0]
                return first && first.coin ? String(first.coin) : ''
            }catch(e){ return '' }
        },
        _truncate(num, decimals=2){
            try{
                const f = Math.pow(10, decimals)
                return (Math.floor(Number(num)*f)/f).toFixed(decimals)
            }catch(e){ return String(num) }
        },
        // 判断是否为“框出来部分”的最后一列（最后一个 hashrate 列）
        isLastHashrateColumn(colIdx){
            try{
                const cols = this.getRenderedColumns()
                for (let i = cols.length - 1; i >= 0; i--) {
                    if (String(cols[i] && cols[i].type).toLowerCase() === 'hashrate') {
                        return i === colIdx
                    }
                }
                return false
            }catch(e){ return false }
        },
        // 仅渲染前 8 个算力列，后接其它非算力列（如收益、回收期）
        getRenderedColumns(){
            try{
                const cols = Array.isArray(this.dynamicColumns) ? this.dynamicColumns : []
                const hashrate = cols.filter(c => String(c && c.type).toLowerCase() === 'hashrate').slice(0, 8)
                const others = cols.filter(c => String(c && c.type).toLowerCase() !== 'hashrate')
                return [...hashrate, ...others]
            }catch(e){ return [] }
        },
        // 打开动态搜索弹窗
        handleOpenDynamicSearch(){
            this.dynamicSearch.visible = true
            this.dynamicSearch.keyword = ''
        },
        // 确认搜索：向后端请求新的 columns/rows，替换动态表格
        async handleConfirmDynamicSearch(){
            const keyword = (this.dynamicSearch.keyword || '').trim()
            this.dynamicSearch.visible = false
            await this.fetchDynamicTable({ shopId: this.params.id, type: 1, keyword })
        },
        // 拉取动态表格数据（占位实现：如果后端已就绪，直接替换为真实接口）
        async fetchDynamicTable(params){
            try{
                // 这里预留与后端对接：
                // 期待返回格式：{ code, data: { meta, columns, rows } }
                // 示例中用本地 mock 演示：根据 keyword 过滤/调整列
                // 如果没有 keyword，就还原初始 mock
                if (!params || !params.keyword) {
                    return
                }
                // 简单模拟：当 keyword 命中 'ERG'，只保留 ERG + 价格/型号/回收期 等少量列
                const kw = String(params.keyword).toUpperCase()
                const baseCols = (this.dynamicColumns || []).filter(c => ['model','price','maxLeaseDays','monthIncome'].includes(c.key))
                const hitCols = (this.dynamicColumns || []).filter(c => String(c.label || c.key).toUpperCase().includes(kw))
                const nextCols = [...(baseCols.length?baseCols:[this.dynamicColumns[0]||[]]), ...hitCols]
                if (nextCols.length) {
                    this.dynamicColumns = nextCols
                    // 行数据无需特别处理（真实环境后端会按列同步返回），这里保留原 rows
                }
            }catch(e){
                // eslint-disable-next-line no-console
                console.warn('fetchDynamicTable mock error', e)
            }
        },
        // 切换矿机种类：0-ASIC，1-GPU
        handleMachineTypeChange(){
            // 切换前清空所有已勾选状态与确认弹窗
            try {
                if (Array.isArray(this.dynamicRows)) {
                    this.dynamicRows.forEach(r => { if (r) this.$set(r, '_selected', false) })
                }
                if (this.confirmAddDialog) {
                    this.confirmAddDialog.items = []
                    this.confirmAddDialog.visible = false
                }
            } catch (e) { /* noop */ }
            // 变更类型后，重新请求数据与支付方式
            this.fetchGetMachineInfo(this.buildQueryParams())
            this.fetchPayTypes()
            // 本地记住用户选择
            try{
              if (window && window.localStorage) {
                window.localStorage.setItem('pl_machineType', String(this.machineType))
              }
            }catch(e){/* noop */}
        },
        // 行币种：优先行内 payCoin > coin，其次取全局表头币种
        getRowCoin(row) {
            try {
                const c = (row && (row.payCoin || row.coin)) || this.getPriceCoinSymbol() || ''
                return String(c).toUpperCase()
            } catch (e) { return '' }
        },
        // 金额格式化：不补0、不四舍五入；返回 {text,truncated,full}
        formatAmount(value, coin) {
            return truncateAmountByCoin(value, coin)
        },
        // 数值格式化：最多6位小数，截断不补0
        formatNum6(value) {
            return truncateTo6(value)
        },
        /**
         * 首次加载时，将“支付方式筛选”的默认选中值设为与价格列币种一致，
         * 并同步 filters.chain/filters.coin；仅执行一次，不触发额外查询。
         */
        ensureDefaultPayFilterSelection() {
            try {
                if (this.payFilterDefaultApplied) return
                const payList = Array.isArray(this.paymentMethodList) ? this.paymentMethodList : []
                if (!payList.length) return
                const coinSymbol = (this.getPriceCoinSymbol && this.getPriceCoinSymbol()) || ''
                if (!coinSymbol) return
                const hit = payList.find(it => String(it && it.payCoin).toUpperCase() === String(coinSymbol).toUpperCase())
                if (!hit) return
                const key = `${hit.payChain || ''}|${hit.payCoin || ''}`
                this.selectedPayKey = key
                this.filters.chain = String(hit.payChain || '').trim()
                this.filters.coin = String(hit.payCoin || '').trim()
                this.payFilterDefaultApplied = true
            } catch (e) { /* noop */ }
        },
        // 切换排序：field in ['priceSort','powerSort','powerDissipationSort']
        handleToggleSort(field) {
            try {
                if (!this.sortStates) this.sortStates = {}
                if (this.activeSortField !== field) {
                    // 切换到新的字段：默认从升序开始（true）
                    // 先将其它字段复位为升序（▲）
                    Object.keys(this.sortStates).forEach(k => { this.sortStates[k] = true })
                    this.activeSortField = field
                    // 后端默认升序，首次点击应为降序
                    this.sortStates[field] = false
                } else {
                    // 同一字段：升降序切换
                    this.sortStates[field] = !this.sortStates[field]
                }
                const params = this.buildQueryParams()
                this.fetchGetMachineInfo(params)
            } catch (e) { /* noop */ }
        },
        // 组合查询参数：店铺入口，必须包含 shopId 与 type（0-ASIC，1-GPU）
        buildQueryParams() {
            const q = { shopId: this.params.id, type: this.machineType }
            // 分页参数始终透传
            try {
                if (this.params && this.params.pageNum != null) q.pageNum = this.params.pageNum
                if (this.params && this.params.pageSize != null) q.pageSize = this.params.pageSize
            } catch (e) { /* noop */ }
            // 仅当用户真实填写（>0）时才传参；默认/空值不传
            const addNum = (obj, key, name) => {
                const raw = obj[key]
                if (raw === null || raw === undefined || raw === '') return
                const n = Number(raw)
                if (Number.isFinite(n) && n > 0) q[name] = n
            }
            // 支付方式条件：有值才传
            if (this.filters.chain && String(this.filters.chain).trim()) q.chain = String(this.filters.chain).trim()
            if (this.filters.coin && String(this.filters.coin).trim()) q.coin = String(this.filters.coin).trim()
            if (this.filters.unit && String(this.filters.unit).trim()) q.unit = String(this.filters.unit).trim()
            addNum(this.filters, 'minPrice', 'minPrice')
            addNum(this.filters, 'maxPrice', 'maxPrice')
            addNum(this.filters, 'minPower', 'minPower')
            addNum(this.filters, 'maxPower', 'maxPower')
            addNum(this.filters, 'minPowerDissipation', 'minPowerDissipation')
            addNum(this.filters, 'maxPowerDissipation', 'maxPowerDissipation')
            // 排序参数：仅在用户点击某一列后传当前列
            try {
                if (this.activeSortField) {
                    const s = this.sortStates || {}
                    q[this.activeSortField] = !!s[this.activeSortField]
                }
            } catch (e) { /* noop */ }
            return q
        },
        // 拉取支付方式（兼容 shopId）
        async fetchPayTypes() {
            try {
                // 现规则：商品详情由店铺入口进入，使用 shopId 查询支付方式
                // 为兼容后端两种入参，优先传 shopId，后端若仍使用 productId 也能兼容处理
                const res = await getPayTypes({ shopId: this.params.id, productId: this.params.id })
                // 接口示例：{ code: 0, data: [ { payChain, payCoin, payCoinImage, shopId } ], msg: '' }
                if (res && (res.code === 0 || res.code === 200)) {
                    const list = Array.isArray(res.data) ? res.data : []
                    this.paymentMethodList = list
                    // 支付方式加载后尝试设置默认筛选
                    this.ensureDefaultPayFilterSelection()
                }
            } catch (e) {
                // 忽略错误，保持页面可用
                this.paymentMethodList = []
            }
        },

        async fetchGetMachineInfo(params) {
            this.productDetailLoading = true
            // 改为使用店铺机器列表接口
            const res = await getShopMachineList(params)
            if (res && (res.code === 200 || res.code === 0)) {
                const root = (res && res.data) ? res.data : res
                const columns = Array.isArray(root.columns) ? root.columns : (Array.isArray(res.columns) ? res.columns : [])
                const rows = Array.isArray(root.rows) ? root.rows : (Array.isArray(res.rows) ? res.rows : [])
                const total = Number(root.total != null ? root.total : (res.total != null ? res.total : 0))
                this.total = Number.isFinite(total) ? total : 0
                // 动态表格：列与行
                this.dynamicColumns = columns
                this.dynamicRows = rows.map(r => ({
                    saleNumbers: 0,
                    saleOutNumbers: 0,
                    leaseTime: 1,
                    purchaseQuantity: 1,
                    _selected: false,
                    ...r
                }))
                // 根据 rows 的 priceList 设置默认支付方式
                this.ensureDefaultPayFilterFromPrices()
                // 若后端同步返回支付方式，刷新本地支付方式
                try {
                    const payList = root && root.payConfigList
                    if (Array.isArray(payList) && payList.length) {
                        this.paymentMethodList = payList
                        this.ensureDefaultPayFilterSelection()
                    }
                } catch (e) { /* noop */ }
            }

            this.productDetailLoading = false
        },
        /**
         * 加载商品详情
         */
        async loadProduct() {
            try {
                this.loading = true
                const productId = this.$route.params.id
                this.product = await getProductById(productId)

                if (!this.product) {
                    this.$message({
                        message: '商品不存在',
                        type: 'error',
                        showClose: true
                    })
                }
            } catch (error) {
                console.error('加载商品详情失败:', error)
                this.$message({
                    message: '加载商品详情失败，请稍后重试',
                    type: 'error',
                    showClose: true
                })
            } finally {
                this.loading = false
            }
        },
        //加入购物车
        async fetchAddCart(params) {
            const res = await addCart(params)

            return res
        },
        //查询购物车列表
        async fetchGetGoodsList(params) {
            const res = await getGoodsListV2(params)
            // 统计当前商品在购物车中已有的机器ID，用于禁用和默认勾选
            try {
                const productId = this.params && this.params.id ? Number(this.params.id) : Number(this.$route.params.id)
                // 兼容两种返回结构：1) 旧：直接是商品分组数组 2) 新：店铺数组 → shoppingCartInfoDtoList
                const rawRows = Array.isArray(res && res.rows)
                    ? res.rows
                    : Array.isArray(res && res.data && res.data.rows)
                        ? res.data.rows
                        : Array.isArray(res && res.data)
                            ? res.data
                            : []
                // 扁平化为商品分组
                const groups = rawRows.length && rawRows[0] && Array.isArray(rawRows[0].shoppingCartInfoDtoList)
                    ? rawRows.flatMap(shop => Array.isArray(shop.shoppingCartInfoDtoList) ? shop.shoppingCartInfoDtoList : [])
                    : rawRows
                const matched = groups.filter(g => Number(g.productId) === productId)
                const ids = new Set()
                const compositeKeys = new Set()
                matched.forEach(r => {
                    const list = Array.isArray(r.productMachineDtoList) ? r.productMachineDtoList : []
                    list.forEach(m => {
                        if (!m) return
                        if (m.id !== undefined && m.id !== null) ids.add(String(m.id))
                        if (m.user && m.miner) compositeKeys.add(`${String(m.user)}|${String(m.miner)}`)
                    })
                })
                this.cartMachineIdSet = ids
                this.cartCompositeKeySet = compositeKeys
                // 计算购物车总数量并通知头部，避免页面初次加载时徽标显示为0
                try {
                    const totalCount = groups.reduce((sum, g) => sum + (Array.isArray(g && g.productMachineDtoList) ? g.productMachineDtoList.length : 0), 0)
                    if (Number.isFinite(totalCount)) {
                        window.dispatchEvent(new CustomEvent('cart-updated', { detail: { count: totalCount } }))
                    }
                } catch (e) { /* noop */ }
                // 展开表格渲染后，默认勾选并禁用这些行
                this.$nextTick(() => {
                    this.cartLoaded = true
                    this.autoSelectAndDisable()
                })
            } catch (e) {
                console.warn('解析购物车数据失败', e)
            }
        },

        /**
         * 处理返回
         */
        handleBack() {
            this.$router.push('/productList')
        },



        /**
         * 点击系列行：切换展开/收起
         * @param {Object} row - 当前行
         */
        handleSeriesRowClick(row) {
            const key = row.id
            const lockedIds = Object.keys(this.selectedMap).filter(k => (this.selectedMap[k] || []).length > 0)
            const opened = this.expandedRowKeys.includes(key)
            if (opened) {
                // 关闭当前行，仅保留已勾选的行展开
                this.expandedRowKeys = lockedIds
            } else {
                // 打开当前行，同时保留已勾选的行展开
                this.expandedRowKeys = Array.from(new Set([key, ...lockedIds]))
            }
        },

        /**
         * 外层系列行样式
         */
        handleGetSeriesRowClassName() {
            return 'series-clickable-row'
        },

        // 子表选择变化
        handleInnerSelectionChange(parentRow, selections) {
            const key = parentRow.id
            this.$set(this.selectedMap, key, selections)
            const lockedIds = Object.keys(this.selectedMap).filter(k => (this.selectedMap[k] || []).length > 0)
            // 更新展开：锁定的行始终展开
            const openedSet = new Set(this.expandedRowKeys)
            lockedIds.forEach(id => openedSet.add(id))
            // 清理不再勾选且不是当前展开的行
            this.expandedRowKeys = Array.from(openedSet).filter(id => lockedIds.includes(id) || id === key || this.expandedRowKeys.includes(id))
        },

        // 展开行变化时：已取消自动与购物车对比，无需勾选/禁用
        handleExpandChange(row, expandedRows) {
            // no-op
        },

        // 已取消对比购物车的自动勾选/禁用逻辑
        autoSelectAndDisable() { },

        // 选择器可选控制：已在购物车中的机器不可再选
        isSelectable(row, index) {
            // 不再通过 selectable 禁用，以便勾选可见；通过行样式和交互阻止点击
            return true
        },

        // 判断在特定父行下是否已选择（配合自定义checkbox使用）
        isSelectedByParent(parentRow, row) {
            const key = parentRow && parentRow.id
            const list = (key && this.selectedMap[key]) || []
            return !!list.find(it => it && it.id === row.id)
        },

        // 手动切换选择（自定义checkbox与 selectedMap 同步），并维护每行的 _selected 状态
        handleManualSelect(parentRow, row, checked) {
            // 禁用：已售出或售出中的机器不可选择
            if (row && (row.saleState === 1 || row.saleState === 2)) {
                this.$message.warning('该机器已售出或售出中，无法选择')
                this.$set(row, '_selected', false)
                return
            }
            // 无价格：不可选择
            try {
                const hasPrice = (Array.isArray(row && row.priceList) && row.priceList.some(it => it && it.price !== null && it.price !== undefined))
                    || (row && row.price !== null && row.price !== undefined && row.price !== '')
                if (!hasPrice) {
                    this.$message.warning('该机器暂无价格，无法选择')
                    this.$set(row, '_selected', false)
                    return
                }
            } catch (e) { /* noop */ }
            const key = parentRow.id
            const list = (this.selectedMap[key] && [...this.selectedMap[key]]) || []
            const idx = list.findIndex(it => it && it.id === row.id)
            if (checked && idx === -1) list.push(row)
            if (!checked && idx > -1) list.splice(idx, 1)
            this.$set(this.selectedMap, key, list)
            this.$set(row, '_selected', !!checked)
        },

        // 为子表中已在购物车的行添加只读样式，并阻止点击取消
        handleGetInnerRowClass({ row }) {
            if (!row) return ''
            return (row.saleState === 1 || row.saleState === 2) ? 'sold-row' : ''
        },

        /**
         * 子行：减少数量
         * @param {number} groupIndex - 系列索引
         * @param {number} variantIndex - 变体索引
         */
        handleDecreaseVariantQuantity(groupIndex, variantIndex) {
            const item = this.productListData[groupIndex].variants[variantIndex]
            if (item.quantity > 1) {
                item.quantity--
            }
        },

        /**
         * 子行：增加数量
         * @param {number} groupIndex - 系列索引
         * @param {number} variantIndex - 变体索引
         */
        handleIncreaseVariantQuantity(groupIndex, variantIndex) {
            const item = this.productListData[groupIndex].variants[variantIndex]
            if (item.quantity < 99) {
                item.quantity++
            }
        },

        /**
         * 子行：输入数量校验
         * @param {number} groupIndex - 系列索引
         * @param {number} variantIndex - 变体索引
         */
        handleVariantQuantityInput(groupIndex, variantIndex) {
            const item = this.productListData[groupIndex].variants[variantIndex]
            const q = Number(item.quantity)
            if (!q || q < 1) item.quantity = 1
            if (q > 99) item.quantity = 99
        },

        /**
         * 子行：加入购物车
         * @param {Object} variant - 子项行数据
         */
        handleAddVariantToCart(variant) {
            if (!variant || !variant.onlyKey) return
            try {
                addToCart({
                    id: variant.onlyKey,
                    title: variant.model,
                    price: variant.price,
                    quantity: variant.quantity
                })
                this.$message.success(`已添加 ${variant.quantity} 件 ${variant.model} 到购物车`)
                variant.quantity = 1
            } catch (error) {
                console.error('添加到购物车失败:', error)

            }
        },
        // 统一加入购物车
        handleAddSelectedToCart() {
            const allSelected = Object.values(this.selectedMap).flat().filter(Boolean)
            if (!allSelected.length) {
                this.$message.warning('请先勾选至少一台矿机')
                return
            }
            try {
                allSelected.forEach(item => {
                    addToCart({
                        id: item.onlyKey || item.id,
                        title: item.type || item.model || '矿机',
                        price: item.price,
                        quantity: 1,
                        leaseTime: Number(item.leaseTime || 1)
                    })
                })
                this.$message.success(`已加入 ${allSelected.length} 台矿机到购物车`)
                this.selectedMap = {}
            } catch (e) {
                console.error('统一加入购物车失败', e)

            }
        },
        // 打开确认弹窗（基于动态表格的勾选行）
        handleOpenAddToCartDialog() {
            const rows = Array.isArray(this.dynamicRows) ? this.dynamicRows : []
            const picked = rows.filter(r => !!r && !!r._selected)
            if (!picked.length) {
                this.$message.warning('请先勾选至少一台矿机')
                return
            }
            this.confirmAddDialog.items = picked.map(r => ({
                ...r,
                leaseTime: Number(r.leaseTime || 1),
                purchaseQuantity: Number(r.purchaseQuantity || 1)
            }))
            this.confirmAddDialog.visible = true
        },
        // 确认加入：调用 addGoodsV2（按条提交），GPU 不传 numbers
        async handleConfirmAddSelectedToCart() {
            const items = Array.isArray(this.confirmAddDialog.items) ? this.confirmAddDialog.items.filter(Boolean) : []
            if (!items.length) {
                this.$message.warning('请先勾选至少一台矿机')
                return
            }
            try {
                // 按接口要求：一次性传数组，每个对象代表一个勾选商品
                const payload = items.map(it => {
                    const obj = {
                        id: it.id,
                        leaseTime: Number(it.leaseTime || 1)
                    }
                    if (this.machineType === 0) {
                        obj.numbers = Number(it.purchaseQuantity || 1)
                    }
                    return obj
                })
                const res = await addGoodsV2(payload)
                if (res && (res.code === 0 || res.code === 200)) {
                    this.$message({
                        message: `已加入 ${items.length} 台矿机到购物车`,
                        type: 'success',
                        duration: 3000,
                        showClose: true
                    })
                }
             
                this.confirmAddDialog.visible = false
                // 清空勾选
                try {
                    (this.dynamicRows || []).forEach(r => { if (r) this.$set(r, '_selected', false) })
                } catch (e) { /* noop */ }
                // 通知头部刷新
                try { window.dispatchEvent(new CustomEvent('cart-updated')) } catch (e) { /* noop */ }
            } catch (e) {
                // eslint-disable-next-line no-console
                console.error('addGoodsV2 error:', e)
                this.$message.error('加入购物车失败，请稍后重试')
            }
        },

        // 取消所有商品勾选（内层表格的自定义 checkbox）
        clearAllSelections() {
            try {
                // 清空选中映射（遗留字段）
                this.selectedMap = {}
                if (Array.isArray(this.machineList) && this.machineList.length) {
                    this.machineList.forEach(m => { if (m) this.$set(m, '_selected', false) })
                    return
                }
                const groups = Array.isArray(this.productListData) ? this.productListData : []
                groups.forEach(g => {
                    const list = Array.isArray(g.productMachines) ? g.productMachines : []
                    list.forEach(m => { if (m) this.$set(m, '_selected', false) })
                })
            } catch (e) { /* noop */ }
        },

        /**
         * 减少数量
         * @param {number} rowIndex - 表格行索引
         */
        handleDecreaseQuantity(rowIndex) {
            if (this.tableData[rowIndex].quantity > 1) {
                this.tableData[rowIndex].quantity--
            }
        },

        /**
         * 增加数量
         * @param {number} rowIndex - 表格行索引
         */
        handleIncreaseQuantity(rowIndex) {
            if (this.tableData[rowIndex].quantity < 99) {
                this.tableData[rowIndex].quantity++
            }
        },

        /**
         * 处理数量输入
         * @param {number} rowIndex - 表格行索引
         */
        handleQuantityInput(rowIndex) {
            const quantity = this.tableData[rowIndex].quantity
            if (quantity < 1) {
                this.tableData[rowIndex].quantity = 1
            } else if (quantity > 99) {
                this.tableData[rowIndex].quantity = 99
            }
        },

        /**
         * 处理数量输入框失焦
         * @param {number} rowIndex - 表格行索引
         */
        handleQuantityBlur(rowIndex) {
            const quantity = this.tableData[rowIndex].quantity
            if (!quantity || quantity < 1) {
                this.tableData[rowIndex].quantity = 1
            } else if (quantity > 99) {
                this.tableData[rowIndex].quantity = 99
            }
        },

        /**
         * 添加到购物车
         * @param {Object} rowData - 表格行数据
         */
        handleAddToCart(rowData) {
            if (!rowData || rowData.quantity < 1) {
                this.$message.warning('请选择有效的数量')
                return
            }

            try {
                addToCart({
                    id: rowData.date, // 使用矿机名称作为ID
                    title: rowData.date,
                    price: rowData.price,
                    quantity: rowData.quantity,
                    leaseTime: Number(rowData.leaseTime || 1)
                })

                this.$message.success(`已添加 ${rowData.quantity} 件 ${rowData.date} 到购物车`)

                // 重置数量
                rowData.quantity = 1
            } catch (error) {
                console.error('添加到购物车失败:', error)
                this.$message.error('添加到购物车失败，请稍后重试')
            }
        },
        handleSizeChange(val) {
            console.log(`每页 ${val} 条`);
            this.params.pageSize = val;
            this.params.pageNum = 1;
            this.currentPage = 1;
            // 携带当前激活的排序字段
            this.fetchGetMachineInfo(this.buildQueryParams());
         
          },
          handleCurrentChange(val) {
            console.log(`当前页: ${val}`);
            this.params.pageNum = val;
            // 携带当前激活的排序字段
            this.fetchGetMachineInfo(this.buildQueryParams());
                    },
    }
}