<template>
  <div class="user-goods-list">
    <el-card class="main-container" shadow="never">
      <!-- 统计卡片 -->
      <div class="stats-row">
        <div class="stat-card" :class="{ active: query.status === 'all' }" @click="handleStatusCard('all')">
          <div class="stat-icon stat-icon-total"><el-icon><Box /></el-icon></div>
          <div class="stat-body">
            <div class="stat-label">商品总数</div>
            <div class="stat-value">{{ countTotal }}</div>
          </div>
        </div>
        <div class="stat-card" :class="{ active: query.status === 'normal' }" @click="handleStatusCard('normal')">
          <div class="stat-icon stat-icon-normal"><el-icon><CircleCheck /></el-icon></div>
          <div class="stat-body">
            <div class="stat-label">正常</div>
            <div class="stat-value">{{ counts.normal }}</div>
          </div>
        </div>
        <div class="stat-card" :class="{ active: query.status === 'expired' }" @click="handleStatusCard('expired')">
          <div class="stat-icon stat-icon-expired"><el-icon><Clock /></el-icon></div>
          <div class="stat-body">
            <div class="stat-label">已到期</div>
            <div class="stat-value">{{ counts.expired }}</div>
          </div>
        </div>
        <div class="stat-card" :class="{ active: query.status === 'deleted' }" @click="handleStatusCard('deleted')">
          <div class="stat-icon stat-icon-deleted"><el-icon><Delete /></el-icon></div>
          <div class="stat-body">
            <div class="stat-label">已删除</div>
            <div class="stat-value">{{ counts.deleted }}</div>
          </div>
        </div>
      </div>

      <!-- 筛选与操作栏 -->
      <div class="filter-section">
        <div class="filter-content">
          <el-form :inline="true" class="search-form">
            <el-form-item label="用户ID">
              <el-input :model-value="filterUserName || (query.user_id ? `${query.user_id}` : '')"
                readonly placeholder="筛选用户" clearable style="width:140px;cursor:pointer"
                @click="showFilterUserSelector = true"
                @clear="query.user_id = ''; filterUserName = ''; handleSearch()" />
            </el-form-item>
            <el-form-item label="商品ID">
              <el-input :model-value="filterGoodName || (query.good_id ? `${query.good_id}` : '')"
                readonly placeholder="筛选商品" clearable style="width:140px;cursor:pointer"
                @click="showFilterProductSelector = true"
                @clear="query.good_id = ''; filterGoodName = ''; handleSearch()" />
            </el-form-item>
            <el-form-item label="关键词">
              <el-input v-model="query.key" placeholder="搜索关键词" clearable style="width:180px"
                @keyup.enter="handleSearch" @clear="handleSearch">
                <template #prefix><el-icon><Search /></el-icon></template>
              </el-input>
            </el-form-item>
            <el-form-item label="状态">
              <el-select v-model="query.status" style="width:120px" @change="handleSearch">
                <el-option label="全部" value="all" />
                <el-option label="正常" value="normal" />
                <el-option label="已到期" value="expired" />
                <el-option label="已删除" value="deleted" />
              </el-select>
            </el-form-item>
            <el-form-item>
              <el-button type="primary" @click="handleSearch">
                <el-icon><Search /></el-icon>查询
              </el-button>
              <el-button @click="query.user_id = ''; query.good_id = ''; query.key = ''; query.status = 'all'; filterUserName = ''; filterGoodName = ''; handleSearch()">重置</el-button>
            </el-form-item>
          </el-form>
          <div class="action-bar">
            <el-button type="primary" @click="handleCreate">
              <el-icon><Plus /></el-icon>新增用户商品
            </el-button>
            <el-button type="success" @click="loadList">
              <el-icon><Refresh /></el-icon>刷新
            </el-button>
          </div>
        </div>
      </div>

      <!-- 数据表格 -->
      <div class="table-section">
        <!-- 骨架屏 -->
        <div v-if="loading && list.length === 0" class="skeleton-container">
          <div v-for="i in 5" :key="i" class="skeleton-row">
            <div class="skeleton-cell" style="width:60px"></div>
            <div class="skeleton-cell" style="width:140px"></div>
            <div class="skeleton-cell" style="flex:1;min-width:120px"></div>
            <div class="skeleton-cell" style="width:80px"></div>
            <div class="skeleton-cell" style="width:100px"></div>
            <div class="skeleton-cell" style="width:160px"></div>
            <div class="skeleton-cell" style="width:140px;height:32px"></div>
          </div>
        </div>

        <el-table
          v-else
          :data="list"
          v-loading="loading"
          stripe
          style="width:100%"
          :header-cell-style="{ background: '#f8f9fa', color: '#2c3e50', fontWeight: 600, fontSize: '13px' }"
        >
          <el-table-column prop="id" label="ID" width="80" />
          <el-table-column label="用户" min-width="140">
            <template #default="{ row }">
              <div class="user-cell">
                <el-link v-if="row.userId || row.user_id" type="primary" :underline="false" @click.stop="router.push({ path: '/user/detail', query: { user_id: row.userId || row.user_id } })">{{ row.user?.UserName || row.user?.username || '-' }}</el-link>
                <span v-else class="user-name">-</span>
                <span class="user-id">({{ row.userId || row.user_id || '-' }})</span>
              </div>
            </template>
          </el-table-column>
          <el-table-column label="商品" min-width="180" show-overflow-tooltip>
            <template #default="{ row }">
              <el-link v-if="row.good?.name" type="primary" :underline="false" @click.stop="handleDetail(row)">{{ row.good.name }}</el-link>
              <span v-else>-</span>
              <span style="color:#909399;font-size:12px"> (ID:{{ row.good?.id || row.goodId || '-' }})</span>
            </template>
          </el-table-column>
          <el-table-column label="标签" width="100">
            <template #default="{ row }">
              <el-tag v-if="row.tag" size="small" type="success">{{ row.tag }}</el-tag>
              <span v-else class="text-muted">-</span>
            </template>
          </el-table-column>
          <el-table-column label="状态" width="100">
            <template #default="{ row }">
              <el-tooltip v-if="isDeleted(row)" :content="`删除于 ${formatTime(row.deleteAt || row.DeleteAt || row.deleted_at)}`" placement="top">
                <el-tag size="small" type="danger">已删除</el-tag>
              </el-tooltip>
              <el-tag v-else-if="isExpired(row)" size="small" type="warning">已到期</el-tag>
              <el-tag v-else size="small" type="success">正常</el-tag>
            </template>
          </el-table-column>
          <el-table-column label="套餐ID" width="90">
            <template #default="{ row }">{{ row.goodPlanId || row.good_plan_id || '-' }}</template>
          </el-table-column>
          <el-table-column label="订单" min-width="180" show-overflow-tooltip>
            <template #default="{ row }">
              <el-link v-if="row.orderId" type="primary" :underline="false" @click.stop="router.push({ path: '/order/list', query: { order_id: row.orderId } })">{{ row.order?.name || `订单 #${row.orderId}` }}</el-link>
              <span v-else>-</span>
            </template>
          </el-table-column>
          <el-table-column label="续费价格" width="110">
            <template #default="{ row }">
              <span v-if="row.renewPrice || row.renew_price" class="price-text">¥{{ ((row.renewPrice || row.renew_price) / 100).toFixed(2) }}</span>
              <span v-else class="text-muted">-</span>
            </template>
          </el-table-column>
          <el-table-column label="到期时间" width="170">
            <template #default="{ row }">
              <span :class="{ 'expire-permanent': formatExpireTime(row.expireTime || row.expire_time) === '永久' }">
                {{ formatExpireTime(row.expireTime || row.expire_time) }}
              </span>
            </template>
          </el-table-column>
          <el-table-column label="操作" width="180" fixed="right">
            <template #default="{ row }">
              <el-button link type="primary" size="small" @click="handleDetail(row)">详情</el-button>
              <el-button link type="primary" size="small" @click="handleEdit(row)">编辑</el-button>
              <el-dropdown trigger="click" @command="cmd => handleMoreCmd(cmd, row)" style="margin-left:8px">
                <el-button link type="primary" size="small" style="transform: translateY(4px);">更多<el-icon style="margin-left:2px"><ArrowDown /></el-icon></el-button>
                <template #dropdown>
                  <el-dropdown-menu>
                    <el-dropdown-item command="remind">提醒记录</el-dropdown-item>
                    <el-dropdown-item command="send">发送提醒</el-dropdown-item>
                    <el-dropdown-item command="delete" divided style="color:#F56C6C">删除商品</el-dropdown-item>
                  </el-dropdown-menu>
                </template>
              </el-dropdown>
            </template>
          </el-table-column>

          <!-- 空状态 -->
          <template #empty>
            <el-empty description="暂无用户商品数据" :image-size="120" />
          </template>
        </el-table>

        <!-- 分页 -->
        <el-pagination
          v-model:current-page="query.page"
          v-model:page-size="query.count"
          :page-sizes="[10, 20, 50]"
          :total="total"
          layout="total, sizes, prev, pager, next, jumper"
          @size-change="s => { query.count = s; query.page = 1; loadList() }"
          @current-change="p => { query.page = p; loadList() }"
          background
          class="pagination"
        />
      </div>
    </el-card>

    <!-- 新增弹窗 -->
    <el-dialog v-model="createVisible" title="新增用户商品" width="600px" destroy-on-close class="scrollable-dialog">
      <el-form ref="createFormRef" :model="createForm" :rules="createRules" label-width="110px">
        <el-form-item label="商品" prop="good_id">
          <div class="selector-row">
            <el-input :model-value="createForm._goodName || (createForm.good_id ? `商品 #${createForm.good_id}` : '')"
              readonly placeholder="请选择商品" style="flex:1" />
            <el-button type="primary" @click="showProductSelector = true" style="margin-left:8px">选择</el-button>
            <el-button v-if="createForm.good_id" @click="createForm.good_id = 0; createForm._goodName = ''; createForm._goodTag = ''; createForm.item_id = 0; createForm._itemName = ''; clearArgsConfig()" style="margin-left:4px">清除</el-button>
          </div>
        </el-form-item>
        <el-form-item label="用户" prop="user_id">
          <div class="selector-row">
            <el-input :model-value="createForm._userName || (createForm.user_id ? `用户 #${createForm.user_id}` : '')"
              readonly placeholder="请选择用户" style="flex:1" />
            <el-button type="primary" @click="showUserSelector = true" style="margin-left:8px">选择</el-button>
            <el-button v-if="createForm.user_id" @click="createForm.user_id = 0; createForm._userName = ''" style="margin-left:4px">清除</el-button>
          </div>
        </el-form-item>
        <el-form-item label="订单">
          <div class="selector-row">
            <el-input :model-value="createForm._orderName || (createForm.order_id ? `订单 #${createForm.order_id}` : '')"
              readonly placeholder="可选" style="flex:1" />
            <el-button type="primary" @click="showOrderSelector = true" style="margin-left:8px">选择</el-button>
            <el-button v-if="createForm.order_id" @click="createForm.order_id = 0; createForm._orderName = ''" style="margin-left:4px">清除</el-button>
          </div>
        </el-form-item>
        <el-form-item label="套餐">
          <div class="selector-row">
            <el-input :model-value="createForm._planName || (createForm.good_plan_id ? `套餐 #${createForm.good_plan_id}` : '')"
              readonly placeholder="可选，选择后自动填入参数" style="flex:1" />
            <el-button type="primary" @click="showPlanSelector = true" style="margin-left:8px">选择</el-button>
            <el-button v-if="createForm.good_plan_id" @click="createForm.good_plan_id = 0; createForm._planName = ''" style="margin-left:4px">清除</el-button>
          </div>
        </el-form-item>

        <!-- 订单参数配置 -->
        <el-form-item label="订单参数">
          <div class="selector-row">
            <el-input :model-value="createForm.order_args ? `已配置 ${argsCount} 个参数` : ''"
              readonly placeholder="可选，点击配置参数" style="flex:1" />
            <el-button type="primary" @click="openArgsDialog" :disabled="!createForm.good_id" style="margin-left:8px">配置</el-button>
            <el-button v-if="createForm.order_args" @click="createForm.order_args = ''; clearArgsConfig()" style="margin-left:4px">清除</el-button>
          </div>
          <div v-if="!createForm.good_id" class="form-hint disabled">请先选择商品</div>
        </el-form-item>

        <el-form-item label="归属项">
          <div class="selector-row">
            <el-input :model-value="createForm._itemName || (createForm.item_id ? `#${createForm.item_id}` : '')"
              readonly placeholder="可选" style="flex:1" />
            <el-button type="primary" @click="handleItemSelect" :disabled="!createForm.good_id" style="margin-left:8px">
              {{ createForm._goodTag === '云服务器' ? '选择虚拟机' : '使用商品ID' }}
            </el-button>
            <el-button v-if="createForm.item_id" @click="createForm.item_id = 0; createForm._itemName = ''" style="margin-left:4px">清除</el-button>
          </div>
          <div v-if="!createForm.good_id" class="form-hint disabled">请先选择商品</div>
          <div v-else-if="createForm._goodTag === '云服务器'" class="form-hint">云服务器商品，点击选择用户虚拟机作为归属项</div>
          <div v-else class="form-hint">普通商品，点击将商品ID赋值为归属项</div>
        </el-form-item>

        <el-form-item label="续费价格">
          <div class="unit-input-row">
            <el-input-number v-model="createForm._renewYuan" :min="0" :precision="2" controls-position="right" style="flex:1" />
            <span class="unit-text">元</span>
          </div>
        </el-form-item>
        <el-form-item label="基础价格">
          <div class="unit-input-row">
            <el-input-number v-model="createForm._baseYuan" :min="0" :precision="2" controls-position="right" style="flex:1" />
            <span class="unit-text">元</span>
          </div>
        </el-form-item>
        <el-form-item label="到期时间">
          <el-date-picker v-model="createForm.expire_time" type="datetime"
            format="YYYY-MM-DD HH:mm:ss" value-format="YYYY-MM-DD HH:mm:ss" style="width:100%" />
        </el-form-item>
        <el-form-item label="备注">
          <el-input v-model="createForm.note" type="textarea" :rows="2" />
        </el-form-item>
      </el-form>
      <template #footer>
        <div class="dialog-footer">
          <el-button @click="createVisible = false">取消</el-button>
          <el-button type="primary" :loading="submitLoading" @click="submitCreate">确定</el-button>
        </div>
      </template>
    </el-dialog>

    <!-- 编辑弹窗 -->
    <el-dialog v-model="editVisible" title="编辑用户商品" width="600px" destroy-on-close class="scrollable-dialog">
      <el-form :model="editForm" label-width="110px">
        <el-form-item label="归属项">
          <div class="selector-row">
            <el-input :model-value="editForm._itemName || (editForm.item_id ? `#${editForm.item_id}` : '')"
              readonly placeholder="可选" style="flex:1" />
            <el-button type="primary" @click="handleEditItemSelect" :disabled="!editForm._goodId" style="margin-left:8px">
              {{ editForm._goodTag === '云服务器' ? '选择虚拟机' : '使用商品ID' }}
            </el-button>
            <el-button v-if="editForm.item_id" @click="editForm.item_id = 0; editForm._itemName = ''" style="margin-left:4px">清除</el-button>
          </div>
          <div v-if="editForm._goodTag === '云服务器'" class="form-hint">云服务器商品，点击选择用户虚拟机作为归属项</div>
          <div v-else class="form-hint">普通商品，点击将商品ID赋值为归属项</div>
        </el-form-item>
        <el-form-item label="续费价格">
          <div class="unit-input-row">
            <el-input-number v-model="editForm._renewYuan" :min="0" :precision="2" controls-position="right" style="flex:1" />
            <span class="unit-text">元</span>
          </div>
        </el-form-item>
        <el-form-item label="基础价格">
          <div class="unit-input-row">
            <el-input-number v-model="editForm._baseYuan" :min="0" :precision="2" controls-position="right" style="flex:1" />
            <span class="unit-text">元</span>
          </div>
        </el-form-item>
        <el-form-item label="到期时间">
          <el-date-picker v-model="editForm.expire_time" type="datetime"
            format="YYYY-MM-DD HH:mm:ss" value-format="YYYY-MM-DD HH:mm:ss" style="width:100%" />
        </el-form-item>
        <el-form-item label="备注">
          <el-input v-model="editForm.note" type="textarea" :rows="2" />
        </el-form-item>
      </el-form>
      <template #footer>
        <div class="dialog-footer">
          <el-button @click="editVisible = false">取消</el-button>
          <el-button type="primary" :loading="submitLoading" @click="submitEdit">保存</el-button>
        </div>
      </template>
    </el-dialog>

    <ProductSelector v-model="showProductSelector" @confirm="handleProductSelected" />
    <UserSelector v-model:visible="showUserSelector" @select="u => { createForm.user_id = u.user_id; createForm._userName = u.user_name }" />
    <UserSelector v-model:visible="showVmUserSelector" @select="handleVmUserSelect" />
    <OrderSelector v-model="showOrderSelector" @confirm="o => { createForm.order_id = o.id; createForm._orderName = o.name }" />
    <PlanSelector v-model="showPlanSelector" :good-id="createForm.good_id" @confirm="handlePlanSelectedForCreate" />
    <!-- 用户虚拟机选择弹窗 -->
    <el-dialog v-model="showVmListDialog" title="选择用户虚拟机" width="800px" append-to-body destroy-on-close>
      <div style="margin-bottom:12px">
        <el-form :inline="true" size="default">
          <el-form-item label="关键词">
            <el-input v-model="vmListQuery.key" placeholder="搜索" clearable style="width:180px"
              @keyup.enter="loadVmListForItem" @clear="loadVmListForItem" />
          </el-form-item>
          <el-form-item label="用户ID">
            <div class="selector-row">
              <el-input :model-value="vmListQuery._userName || (vmListQuery.user_id ? `用户 #${vmListQuery.user_id}` : '')"
                readonly placeholder="按用户筛选" style="flex:1" @click="showVmUserSelector = true" />
              <el-button v-if="vmListQuery.user_id" @click="vmListQuery.user_id = ''; vmListQuery._userName = ''; loadVmListForItem()" style="margin-left:4px">清除</el-button>
            </div>
          </el-form-item>
          <el-form-item label="状态">
            <el-select v-model="vmListQuery.status" placeholder="筛选状态" clearable style="width:120px" @change="loadVmListForItem">
              <el-option label="运行中" value="running" />
              <el-option label="已停止" value="stopped" />
              <el-option label="未知" value="unknown" />
            </el-select>
          </el-form-item>
          <el-form-item>
            <el-button type="primary" @click="loadVmListForItem">搜索</el-button>
            <el-button @click="loadVmListForItem" :icon="Refresh">刷新</el-button>
            <el-button @click="resetVmListFilters">重置</el-button>
          </el-form-item>
        </el-form>
      </div>
      <el-table :data="vmListForItem" v-loading="vmListLoading" highlight-current-row
        @current-change="r => vmListSelected = r" :height="350" style="width:100%"
        :header-cell-style="{ background: '#f8f9fa', color: '#2c3e50', fontWeight: 600 }">
        <el-table-column prop="id" label="ID" width="80" />
        <el-table-column label="虚拟机名称" min-width="160" show-overflow-tooltip>
          <template #default="{ row }">{{ row.name || '-' }}</template>
        </el-table-column>
        <el-table-column label="配置" min-width="120">
          <template #default="{ row }">
            <div v-if="row.vcpu && row.memory">
              {{ row.vcpu }}核 / {{ formatMemory(row.memory) }}
            </div>
            <span v-else>-</span>
          </template>
        </el-table-column>
        <el-table-column label="状态" width="80">
          <template #default="{ row }">
            <el-tag :type="getStatusType(row.status)" size="small">
              {{ getStatusText(row.status) }}
            </el-tag>
          </template>
        </el-table-column>
        <el-table-column label="绑定状态" width="90">
          <template #default="{ row }">
            <el-tag :type="row.bound ? 'success' : 'info'" size="small">
              {{ row.bound ? '已绑定' : '未绑定' }}
            </el-tag>
          </template>
        </el-table-column>
        <el-table-column label="IP地址" min-width="180" show-overflow-tooltip>
          <template #default="{ row }">{{ row.ips || '-' }}</template>
        </el-table-column>
        <el-table-column label="用户ID" width="80">
          <template #default="{ row }">{{ row.user_id || '-' }}</template>
        </el-table-column>
        <template #empty>
          <el-empty description="暂无虚拟机数据" :image-size="80" />
        </template>
      </el-table>
      <div style="display:flex;justify-content:flex-end;margin-top:12px">
        <el-pagination v-model:current-page="vmListQuery.page" v-model:page-size="vmListQuery.count"
          :total="vmListTotal" :page-sizes="[10,20,50]" layout="total,sizes,prev,pager,next" background
          @size-change="s => { vmListQuery.count = s; vmListQuery.page = 1; loadVmListForItem() }"
          @current-change="p => { vmListQuery.page = p; loadVmListForItem() }" />
      </div>
      <template #footer>
        <div class="dialog-footer">
          <el-button @click="showVmListDialog = false">取消</el-button>
          <el-button type="primary" :disabled="!vmListSelected" @click="confirmVmForItem">确定选择</el-button>
        </div>
      </template>
    </el-dialog>

    <!-- 订单参数配置弹窗 -->
    <el-dialog v-model="showArgsDialog" title="配置订单参数" width="600px" append-to-body destroy-on-close class="scrollable-dialog">
      <div v-if="argsSpecLoading" v-loading="true" style="min-height:120px"></div>
      <el-empty v-else-if="argsSpecList.length === 0" description="该商品暂无参数配置" :image-size="80" />
      <div v-else>
        <div v-for="spec in argsSpecList" :key="spec.id" class="args-spec-item">
          <div class="args-spec-label">
            {{ spec.name }}
            <el-tag v-if="spec.must" size="small" type="danger" style="margin-left:6px">必填</el-tag>
          </div>
          <template v-if="spec.type === 'select' && spec.attrs && spec.attrs.length > 0">
            <el-radio-group v-model="argsValues[spec.id]" size="small" @change="buildArgsJson">
              <el-radio-button v-for="attr in spec.attrs" :key="attr.id" :value="attr.id">{{ attr.name }}</el-radio-button>
            </el-radio-group>
          </template>
          <template v-else-if="spec.type === 'number'">
            <div style="display:flex;align-items:center;gap:12px;flex-wrap:wrap">
              <el-input-number
                v-model="argsDisplayValues[spec.id]"
                :min="hasUnit(spec) ? fromBaseUnit(spec.min ?? 0, argsDisplayUnits[spec.id], getArgKey(spec)) : (spec.min ?? 0)"
                :max="hasUnit(spec) ? fromBaseUnit(spec.max ?? 0, argsDisplayUnits[spec.id], getArgKey(spec)) : (spec.max ?? 0)"
                :step="hasUnit(spec) ? (fromBaseUnit(spec.step ?? 1, argsDisplayUnits[spec.id], getArgKey(spec)) || 1) : (spec.step ?? 1)"
                :step-strictly="true"
                @change="onArgsNumberChange(spec)"
                style="width:200px"
              />
              <el-select v-if="hasUnit(spec)" :model-value="argsDisplayUnits[spec.id]" size="default" style="width:90px" @change="(newUnit) => onArgsUnitChange(spec, newUnit)">
                <el-option v-for="u in getParamUnits(spec)" :key="u" :label="u" :value="u" />
              </el-select>
              <span class="form-hint" style="margin-top:0">范围: {{ spec.min ?? 0 }} ~ {{ spec.max ?? 0 }}
                <template v-if="hasUnit(spec)"> {{ getBaseUnit(getArgKey(spec)) }}</template>，步长: {{ spec.step ?? 1 }}</span>
            </div>
          </template>
          <template v-else>
            <el-input v-model="argsValues[spec.id]" placeholder="请输入值" style="width:200px" @input="buildArgsJson" />
          </template>
        </div>
        <div v-if="createForm.order_args" style="margin-top:16px">
          <div class="form-hint" style="margin-bottom:6px;margin-top:0">生成的参数 JSON：</div>
          <el-input v-model="createForm.order_args" type="textarea" :rows="4" readonly style="font-family:monospace;font-size:12px" />
        </div>
      </div>
      <template #footer>
        <div class="dialog-footer">
          <el-button @click="showArgsDialog = false">取消</el-button>
          <el-button type="primary" @click="showArgsDialog = false">确定</el-button>
        </div>
      </template>
    </el-dialog>

    <!-- 到期提醒记录弹窗 -->
    <el-dialog v-model="remindVisible" title="到期提醒记录" width="700px" destroy-on-close append-to-body>
      <div style="margin-bottom:12px;display:flex;justify-content:space-between;align-items:center">
        <span style="font-size:13px;color:#909399">用户商品 ID: {{ remindGoodsId }}</span>
        <el-button type="primary" size="small" :icon="Refresh" @click="loadRemindList">刷新</el-button>
      </div>
      <el-table :data="remindList" v-loading="remindLoading" stripe size="small" :max-height="400">
        <el-table-column prop="id" label="ID" width="60" />
        <el-table-column label="用户" width="100">
          <template #default="{ row }">{{ row.user?.UserName || row.user?.user_name || `#${row.userId ?? row.user_id ?? '-'}` }}</template>
        </el-table-column>
        <el-table-column label="提醒类型" width="80">
          <template #default="{ row }">
            <el-tag size="small" :type="row.type === 'manual' ? 'warning' : 'info'">{{ row.type === 'manual' ? '手动' : '自动' }}</el-tag>
          </template>
        </el-table-column>
        <el-table-column label="发送方式" width="80">
          <template #default="{ row }">
            <el-tag size="small" :type="row.method === 'sms' ? 'success' : row.method === 'email' ? 'primary' : 'info'">{{ row.method === 'sms' ? '短信' : row.method === 'email' ? '邮件' : (row.method || '-') }}</el-tag>
          </template>
        </el-table-column>
        <el-table-column label="发送状态" width="80">
          <template #default="{ row }">
            <el-tag size="small" :type="row.success ? 'success' : 'danger'">{{ row.success ? '成功' : '失败' }}</el-tag>
          </template>
        </el-table-column>
        <el-table-column label="发送时间" min-width="160">
          <template #default="{ row }">{{ formatRemindTime(row) }}</template>
        </el-table-column>
        <el-table-column label="备注" min-width="120" show-overflow-tooltip>
          <template #default="{ row }">{{ row.note || '-' }}</template>
        </el-table-column>
      </el-table>
      <div style="display:flex;justify-content:flex-end;margin-top:12px" v-if="remindTotal > remindQuery.count">
        <el-pagination v-model:current-page="remindQuery.page" :page-size="remindQuery.count" :total="remindTotal" layout="total, prev, pager, next" small background @current-change="loadRemindList" />
      </div>
    </el-dialog>

    <!-- 筛选区选择器 -->
    <UserSelector v-model:visible="showFilterUserSelector" @select="u => { query.user_id = u.user_id; filterUserName = u.user_name; handleSearch() }" />
    <ProductSelector v-model="showFilterProductSelector" @confirm="p => { query.good_id = p.id; filterGoodName = p.name; handleSearch() }" />
  </div>
</template>

<script setup>
import { ref, reactive, computed, onMounted, watch } from 'vue'
import { useRouter } from 'vue-router'
import { ElMessage, ElMessageBox } from 'element-plus'
import { Plus, Refresh, Search, ArrowDown, Box, CircleCheck, Clock, Delete } from '@element-plus/icons-vue'
import { getUserGoodsList, getUserGoodsCount, createUserGoods, updateUserGoods, deleteUserGoods, getUserVmList, getExpireRemindList, sendExpireRemind } from '@/api/admin/userVm'
import { extractApiError } from '@/utils/kvmErrorUtil'
import { formatToApiTime } from '@/utils/tool'
import { getProductParameterList, getProductPlanDetail } from '@/api/admin/product'
import { hasUnit, getArgKey, getBaseUnit, getParamUnits, getParamDefaultUnit, toBaseUnit, fromBaseUnit } from '@/utils/dynamicUnit'
import ProductSelector from '@/components/admin/ProductSelector.vue'
import UserSelector from '@/components/UserSelector/index.vue'
import OrderSelector from '@/components/admin/OrderSelector.vue'
import PlanSelector from '@/components/admin/PlanSelector.vue'
import dayjs from 'dayjs'

const router = useRouter()
const loading = ref(false)
const list = ref([])
const total = ref(0)
const query = reactive({ page: 1, count: 10, key: '', user_id: '', good_id: '', status: 'all' })
const filterUserName = ref('')
const filterGoodName = ref('')
const showFilterUserSelector = ref(false)
const showFilterProductSelector = ref(false)

// 用户商品数量统计
const counts = reactive({ normal: 0, deleted: 0, expired: 0 })
const countTotal = computed(() => (counts.normal || 0) + (counts.deleted || 0) + (counts.expired || 0))

const formatTime = (t) => t ? dayjs(t).format('YYYY-MM-DD HH:mm:ss') : '-'

const formatExpireTime = (t) => {
  if (!t) return '-'
  const d = dayjs(t)
  if (d.year() < 2000) return '永久'
  return d.format('YYYY-MM-DD HH:mm:ss')
}

// 判断用户商品是否已删除（后端返回 deleteAt 字段，有值即已删除）
const isDeleted = (row) => !!(row?.deleteAt || row?.DeleteAt || row?.deleted_at)

// 判断用户商品是否已到期（永久商品除外）
const isExpired = (row) => {
  const t = row?.expireTime || row?.expire_time
  if (!t) return false
  const d = dayjs(t)
  return d.year() >= 2000 && d.isBefore(dayjs())
}

const formatMemory = (kb) => {
  if (!kb) return '-'
  if (kb >= 1048576) return (kb / 1048576).toFixed(1) + ' GB'
  if (kb >= 1024) return (kb / 1024).toFixed(0) + ' MB'
  return kb + ' KB'
}

const getStatusType = (status) => {
  switch (status) {
    case 'running': return 'success'
    case 'stop': return 'danger'
    case 'stopped': return 'danger'
    default: return 'info'
  }
}

const getStatusText = (status) => {
  switch (status) {
    case 'running': return '运行中'
    case 'stop': return '已停止'
    case 'stopped': return '已停止'
    default: return status || '未知'
  }
}

// 组装筛选参数（count 与 list 共用）
const buildFilterParams = () => {
  const params = {}
  if (query.key) params.key = query.key
  if (query.user_id) params.user_id = parseInt(query.user_id) || undefined
  if (query.good_id) params.good_id = parseInt(query.good_id) || undefined
  return params
}

const loadList = async () => {
  loading.value = true
  try {
    const params = { page: query.page, count: query.count, ...buildFilterParams() }
    if (query.status && query.status !== 'all') params.status = query.status
    const res = await getUserGoodsList(params)
    if (res?.data?.code === 200 && res?.data?.data) {
      const d = res.data.data
      list.value = d.data || (Array.isArray(d) ? d : [])
      total.value = d.all_count ?? d.total ?? list.value.length
    } else { list.value = []; total.value = 0 }
  } catch { list.value = []; total.value = 0 } finally { loading.value = false }
}

// 加载数量统计（透传筛选条件，与列表联动）
const loadCount = async () => {
  try {
    const res = await getUserGoodsCount(buildFilterParams())
    if (res?.data?.code === 200 && res?.data?.data) {
      const d = res.data.data
      counts.normal = d.normal ?? 0
      counts.deleted = d.deleted ?? 0
      counts.expired = d.expired ?? 0
    }
  } catch { /* 统计失败不阻断列表 */ }
}

const handleSearch = () => { query.page = 1; loadList(); loadCount() }

// 点击统计卡片快速切换状态筛选
const handleStatusCard = (status) => {
  query.status = status
  handleSearch()
}

// ---- 订单参数配置 ----
const argsSpecList = ref([])
const argsSpecLoading = ref(false)
const argsValues = reactive({})
const argsDisplayValues = reactive({})
const argsDisplayUnits = reactive({})
const showArgsDialog = ref(false)

const argsCount = computed(() => {
  try { const arr = JSON.parse(createForm.order_args || '[]'); return Array.isArray(arr) ? arr.length : 0 } catch { return 0 }
})

const openArgsDialog = () => {
  if (!createForm.good_id) return
  showArgsDialog.value = true
  if (argsSpecList.value.length === 0) loadArgsSpec(createForm.good_id)
}

const clearArgsConfig = () => {
  argsSpecList.value = []
  for (const k in argsValues) delete argsValues[k]
  createForm.order_args = ''
}

const loadArgsSpec = async (goodId) => {
  if (!goodId) return
  argsSpecLoading.value = true
  try {
    const res = await getProductParameterList({ good_id: goodId })
    if (res?.data?.code === 200) {
      argsSpecList.value = res.data.data || []
      for (const spec of argsSpecList.value) {
        if (spec.type === 'number' && argsValues[spec.id] === undefined) {
          argsValues[spec.id] = spec.min ?? 0
          if (hasUnit(spec)) {
            argsDisplayUnits[spec.id] = getParamDefaultUnit(spec)
            argsDisplayValues[spec.id] = fromBaseUnit(spec.min ?? 0, argsDisplayUnits[spec.id], getArgKey(spec))
          } else {
            argsDisplayValues[spec.id] = spec.min ?? 0
          }
        }
      }
    }
  } catch { argsSpecList.value = [] } finally { argsSpecLoading.value = false }
}

const onArgsNumberChange = (spec) => {
  if (hasUnit(spec)) {
    argsValues[spec.id] = Math.round(toBaseUnit(argsDisplayValues[spec.id] || 0, argsDisplayUnits[spec.id], getArgKey(spec)))
  } else {
    argsValues[spec.id] = argsDisplayValues[spec.id]
  }
  buildArgsJson()
}
const onArgsUnitChange = (spec, newUnit) => {
  const argKey = getArgKey(spec)
  const oldUnit = argsDisplayUnits[spec.id]
  const oldDisplay = argsDisplayValues[spec.id] || 0
  const baseValue = oldUnit ? toBaseUnit(oldDisplay, oldUnit, argKey) : oldDisplay
  argsDisplayUnits[spec.id] = newUnit
  argsDisplayValues[spec.id] = fromBaseUnit(baseValue, newUnit, argKey)
  argsValues[spec.id] = Math.round(baseValue)
  buildArgsJson()
}

const buildArgsJson = () => {
  const argsArray = []
  for (const spec of argsSpecList.value) {
    const val = argsValues[spec.id]
    if (val === undefined || val === '') continue
    if (spec.type === 'select') {
      const attr = spec.attrs?.find(a => a.id === val)
      if (attr) argsArray.push({ arg_id: spec.id, name: spec.name, attr_id: attr.id, value: attr.value || '' })
    } else if (spec.type === 'number') {
      argsArray.push({ arg_id: spec.id, name: spec.name, attr_id: 0, number: Number(val) })
    } else {
      argsArray.push({ arg_id: spec.id, name: spec.name, attr_id: 0, value: String(val) })
    }
  }
  createForm.order_args = argsArray.length > 0 ? JSON.stringify(argsArray) : ''
}

// ---- 新增 ----
const createVisible = ref(false)
const createFormRef = ref(null)
const submitLoading = ref(false)
const showProductSelector = ref(false)
const showUserSelector = ref(false)
const showOrderSelector = ref(false)
const showPlanSelector = ref(false)

const createForm = reactive({
  good_id: 0, _goodName: '', _goodTag: '',
  user_id: 0, _userName: '',
  order_id: 0, _orderName: '',
  good_plan_id: 0, _planName: '',
  order_args: '',
  item_id: 0, _itemName: '',
  _renewYuan: 0, _baseYuan: 0,
  expire_time: '', note: ''
})

const createRules = {
  good_id: [{ required: true, validator: (r, v, cb) => v > 0 ? cb() : cb(new Error('请选择商品')), trigger: 'change' }],
  user_id: [{ required: true, validator: (r, v, cb) => v > 0 ? cb() : cb(new Error('请选择用户')), trigger: 'change' }]
}

const handleCreate = () => {
  Object.assign(createForm, {
    good_id: 0, _goodName: '', _goodTag: '',
    user_id: 0, _userName: '',
    order_id: 0, _orderName: '',
    good_plan_id: 0, _planName: '',
    order_args: '',
    item_id: 0, _itemName: '',
    _renewYuan: 0, _baseYuan: 0,
    expire_time: '', note: ''
  })
  clearArgsConfig()
  createVisible.value = true
}

const handleProductSelected = (p) => {
  createForm.good_id = p.id
  createForm._goodName = p.name || ''
  createForm._goodTag = p.tag || ''
  createForm.item_id = 0
  createForm._itemName = ''
  clearArgsConfig()
}

const handlePlanSelectedForCreate = async (plan) => {
  createForm.good_plan_id = plan.id
  createForm._planName = plan.name || `套餐 #${plan.id}`
  if (plan.args) {
    createForm.order_args = typeof plan.args === 'string' ? plan.args : JSON.stringify(plan.args)
  }
  if (plan.id && createForm.good_id) {
    try {
      const res = await getProductPlanDetail({ good_id: String(createForm.good_id), plan_id: String(plan.id) })
      if (res?.data?.code === 200 && res.data.data?.args) {
        createForm.order_args = typeof res.data.data.args === 'string' ? res.data.data.args : JSON.stringify(res.data.data.args)
      }
    } catch { /* keep what we have */ }
  }
}

// ---- item_id 选择 ----
const vmItemTarget = ref('create')
const showVmListDialog = ref(false)
const vmListForItem = ref([])
const vmListLoading = ref(false)
const vmListSelected = ref(null)
const vmListTotal = ref(0)
const vmListQuery = reactive({ page: 1, count: 10, key: '', user_id: '', status: '', _userName: '' })
const showVmUserSelector = ref(false)

const handleItemSelect = () => {
  if (createForm._goodTag === '云服务器') {
    vmItemTarget.value = 'create'
    showVmListDialog.value = true
    loadVmListForItem()
  } else {
    createForm.item_id = createForm.good_id
    createForm._itemName = `商品 #${createForm.good_id}`
    ElMessage.success('已将商品ID赋值为归属项')
  }
}

const loadVmListForItem = async () => {
  vmListLoading.value = true
  try {
    const params = { page: vmListQuery.page, count: vmListQuery.count }
    if (vmListQuery.key) params.key = vmListQuery.key
    if (vmListQuery.user_id) params.user_id = parseInt(vmListQuery.user_id) || undefined
    if (vmListQuery.status) params.status = vmListQuery.status
    // 传递good_id参数
    if (vmItemTarget.value === 'edit' && editForm._goodId) {
      params.good_id = editForm._goodId
    } else if (vmItemTarget.value === 'create' && createForm.good_id) {
      params.good_id = createForm.good_id
    }
    const res = await getUserVmList(params)
    if (res?.data?.code === 200 && res?.data?.data) {
      const d = res.data.data
      vmListForItem.value = d.data || (Array.isArray(d) ? d : [])
      vmListTotal.value = d.all_count ?? d.total ?? vmListForItem.value.length
    }
  } catch { vmListForItem.value = [] } finally { vmListLoading.value = false }
}

const confirmVmForItem = () => {
  if (!vmListSelected.value) return
  const vm = vmListSelected.value
  if (vmItemTarget.value === 'edit') {
    editForm.item_id = vm.id
    editForm._itemName = `虚拟机 #${vm.id}`
  } else {
    createForm.item_id = vm.id
    createForm._itemName = `虚拟机 #${vm.id}`
  }
  showVmListDialog.value = false
  vmListSelected.value = null
  ElMessage.success('虚拟机已选择')
}

const resetVmListFilters = () => {
  vmListQuery.key = ''
  vmListQuery.user_id = ''
  vmListQuery.status = ''
  vmListQuery._userName = ''
  vmListQuery.page = 1
  loadVmListForItem()
}

const handleVmUserSelect = (user) => {
  vmListQuery.user_id = user.user_id
  vmListQuery._userName = user.user_name
  showVmUserSelector.value = false
  loadVmListForItem()
}

const submitCreate = async () => {
  try { await createFormRef.value?.validate() } catch { return }
  submitLoading.value = true
  try {
    const payload = {
      good_id: createForm.good_id,
      user_id: createForm.user_id,
      item_id: createForm.item_id || 0,
      renew_price: Math.round((createForm._renewYuan || 0) * 100),
      base_price: Math.round((createForm._baseYuan || 0) * 100),
      note: createForm.note || ''
    }
    if (createForm.order_id) payload.order_id = createForm.order_id
    if (createForm.good_plan_id) payload.good_plan_id = createForm.good_plan_id
    if (createForm.order_args) payload.order_args = createForm.order_args
    if (createForm.expire_time) payload.expire_time = formatToApiTime(createForm.expire_time)
    const res = await createUserGoods(payload)
    if (res?.data?.code === 200) { ElMessage.success('创建成功'); createVisible.value = false; loadList() }
    else ElMessage.error(extractApiError(res?.data, '创建失败'))
  } catch (e) { ElMessage.error(extractApiError(e?.response?.data, '创建失败')) } finally { submitLoading.value = false }
}

// ---- 编辑 ----
const editVisible = ref(false)
const editForm = reactive({
  id: 0, note: '', _renewYuan: 0, _baseYuan: 0, expire_time: '',
  item_id: 0, _itemName: '', _goodTag: '', _goodId: 0
})

const handleEdit = (row) => {
  const goodTag = row.tag || row.good?.tag || ''
  const goodId = row.good?.id || row.goodId || 0
  const itemId = row.itemId || row.item_id || 0

  Object.assign(editForm, {
    id: row.id,
    note: row.note || '',
    _renewYuan: ((row.renewPrice || row.renew_price || 0) / 100),
    _baseYuan: ((row.basePrice || row.base_price || 0) / 100),
    expire_time: row.expireTime || row.expire_time || '',
    item_id: itemId,
    _goodTag: goodTag,
    _goodId: goodId,
    _itemName: itemId
      ? (goodTag === '云服务器' ? `虚拟机 #${itemId}` : `商品 #${itemId}`)
      : ''
  })
  editVisible.value = true
}

const handleEditItemSelect = () => {
  if (editForm._goodTag === '云服务器') {
    vmItemTarget.value = 'edit'
    showVmListDialog.value = true
    loadVmListForItem()
  } else {
    editForm.item_id = editForm._goodId
    editForm._itemName = `商品 #${editForm._goodId}`
    ElMessage.success('已将商品ID赋值为归属项')
  }
}

const submitEdit = async () => {
  submitLoading.value = true
  try {
    const payload = {
      id: editForm.id,
      note: editForm.note,
      item_id: editForm.item_id || 0,
      renew_price: Math.round((editForm._renewYuan || 0) * 100),
      base_price: Math.round((editForm._baseYuan || 0) * 100)
    }
    if (editForm.expire_time) payload.expire_time = formatToApiTime(editForm.expire_time)
    const res = await updateUserGoods(payload)
    if (res?.data?.code === 200) { ElMessage.success('保存成功'); editVisible.value = false; loadList() }
    else ElMessage.error(extractApiError(res?.data, '保存失败'))
  } catch (e) { ElMessage.error(extractApiError(e?.response?.data, '保存失败')) } finally { submitLoading.value = false }
}

// ---- 详情 / 删除 ----
const handleDetail = (row) => {
  router.push({ name: 'UserGoodsDetail', params: { id: row.id } })
}

const handleMoreCmd = (cmd, row) => {
  if (cmd === 'remind') openRemindList(row)
  else if (cmd === 'send') handleSendRemind(row)
  else if (cmd === 'delete') handleDelete(row)
}

const handleDelete = (row) => {
  ElMessageBox.confirm(`确定删除该用户商品吗？`, '删除确认', { type: 'warning' })
    .then(async () => {
      try {
        const res = await deleteUserGoods({ id: row.id })
        if (res?.data?.code === 200) { ElMessage.success('删除成功'); loadList() }
        else ElMessage.error(extractApiError(res?.data, '删除失败'))
      } catch (e) { ElMessage.error(extractApiError(e?.response?.data, '删除失败')) }
    }).catch(() => {})
}

// ---- 到期提醒 ----
const remindVisible = ref(false)
const remindLoading = ref(false)
const remindList = ref([])
const remindTotal = ref(0)
const remindGoodsId = ref(0)
const remindQuery = reactive({ page: 1, count: 10 })

const openRemindList = (row) => {
  remindGoodsId.value = row.id
  remindQuery.page = 1
  remindVisible.value = true
  loadRemindList()
}

const formatRemindTime = (row) => {
  const t = row.CreatedAt || row.created_at || row.send_time
  if (!t || t.startsWith('0001')) return '-'
  try { return dayjs(t).format('YYYY-MM-DD HH:mm:ss') } catch { return t }
}

const loadRemindList = async () => {
  remindLoading.value = true
  try {
    const res = await getExpireRemindList({ user_goods_id: remindGoodsId.value, page: remindQuery.page, count: remindQuery.count })
    if (res?.data?.code === 200 && res?.data?.data) {
      const d = res.data.data
      remindList.value = d.data || d.list || (Array.isArray(d) ? d : [])
      remindTotal.value = d.all_count ?? d.meta?.count ?? d.total ?? remindList.value.length
    } else { remindList.value = []; remindTotal.value = 0 }
  } catch { remindList.value = []; remindTotal.value = 0 }
  finally { remindLoading.value = false }
}

const handleSendRemind = (row) => {
  ElMessageBox.confirm(`确定手动发送到期提醒给该用户商品（ID: ${row.id}）吗？`, '发送确认', { type: 'warning', confirmButtonText: '确认发送' })
    .then(async () => {
      try {
        const res = await sendExpireRemind({ user_goods_id: row.id, user_id: row.userId || row.user_id })
        if (res?.data?.code === 200) ElMessage.success('发送成功')
        else ElMessage.error(extractApiError(res?.data, '发送失败'))
      } catch (e) { ElMessage.error(extractApiError(e?.response?.data, '发送失败')) }
    }).catch(() => {})
}

onMounted(() => { loadList(); loadCount() })
</script>

<style scoped>
.user-goods-list {
  padding: 0;
}

.main-container {
  border: 1px solid #e1e8ed;
  background: #ffffff;
}

.stats-row {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 12px;
  padding: 16px 20px;
  border-bottom: 1px solid #e1e8ed;
  background: #fafbfc;
}

.stat-card {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 14px 16px;
  background: #ffffff;
  border: 1px solid #e1e8ed;
  border-radius: 8px;
  cursor: pointer;
  transition: all 0.2s;
}

.stat-card:hover {
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
}

.stat-card.active {
  border-color: #409eff;
  background: #ecf5ff;
}

.stat-icon {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  border-radius: 8px;
  font-size: 20px;
  flex-shrink: 0;
}

.stat-icon-total { background: #eef3ff; color: #4f6ef7; }
.stat-icon-normal { background: #f0faf0; color: #52c41a; }
.stat-icon-expired { background: #fff7e6; color: #fa8c16; }
.stat-icon-deleted { background: #fff1f0; color: #f5222d; }

.stat-body { display: flex; flex-direction: column; }
.stat-label { font-size: 13px; color: #909399; margin-bottom: 2px; }
.stat-value { font-size: 22px; font-weight: 600; color: #2c3e50; line-height: 1.1; }

@media (max-width: 768px) {
  .stats-row { grid-template-columns: repeat(2, 1fr); }
}

:deep(.el-card__body) {
  padding: 0;
}

.filter-section {
  padding: 0;
  border-bottom: 1px solid #e1e8ed;
  background: #fafbfc;
}

.filter-content {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 16px 20px;
  gap: 20px;
  flex-wrap: wrap;
}

.search-form {
  display: flex;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
  margin: 0;
}

.search-form :deep(.el-form-item) {
  margin-bottom: 0;
  margin-right: 0;
}

.action-bar {
  display: flex;
  gap: 12px;
  flex-shrink: 0;
  flex-wrap: wrap;
  align-items: center;
}

.table-section {
  padding: 0;
}

.user-cell {
  display: flex;
  align-items: center;
  gap: 4px;
}

.user-name {
  font-weight: 500;
  color: #303133;
}

.user-id {
  color: #909399;
  font-size: 12px;
}

.price-text {
  color: #e74c3c;
  font-weight: 600;
  font-size: 14px;
}

.expire-permanent {
  color: #67c23a;
  font-weight: 500;
}

.action-buttons {
  display: flex;
  gap: 4px;
  align-items: center;
  flex-wrap: nowrap;
}

.action-buttons .el-button {
  padding: 4px 8px;
}

.pagination {
  padding: 16px 20px;
  border-top: 1px solid #e1e8ed;
  background: #fafbfc;
  justify-content: flex-end;
}

.dialog-footer {
  display: flex;
  justify-content: flex-end;
  gap: 12px;
  padding: 0;
}

.selector-row {
  display: flex;
  align-items: center;
  width: 100%;
}

.form-hint {
  font-size: 12px;
  color: #909399;
  margin-top: 4px;
}

.form-hint.disabled {
  color: #c0c4cc;
}

.args-spec-item {
  margin-bottom: 16px;
  padding-bottom: 16px;
  border-bottom: 1px solid #f0f0f0;
}

.args-spec-item:last-child {
  border-bottom: none;
}

.args-spec-label {
  font-size: 14px;
  font-weight: 500;
  color: #303133;
  margin-bottom: 8px;
}

/* 骨架屏 */
.skeleton-container {
  padding: 20px;
}

.skeleton-row {
  display: flex;
  align-items: center;
  padding: 16px 0;
  border-bottom: 1px solid #f0f0f0;
  gap: 16px;
}

.skeleton-row:last-child {
  border-bottom: none;
}

.skeleton-cell {
  height: 20px;
  background: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%);
  background-size: 200% 100%;
  animation: skeleton-loading 1.5s ease-in-out infinite;
  border-radius: 4px;
}

@keyframes skeleton-loading {
  0% { background-position: 200% 0; }
  100% { background-position: -200% 0; }
}

:global(.scrollable-dialog .el-dialog__body) {
  max-height: 70vh;
  overflow-y: auto;
  overflow-x: hidden;
  scrollbar-width: none;
}

:global(.scrollable-dialog .el-dialog__body::-webkit-scrollbar) {
  display: none;
}

@media (max-width: 768px) {
  .filter-content {
    flex-direction: column;
    align-items: stretch;
    gap: 12px;
  }

  .search-form {
    flex-direction: column;
    width: 100%;
  }

  .search-form :deep(.el-form-item) {
    width: 100%;
  }

  .action-bar {
    width: 100%;
    justify-content: flex-start;
  }
}

.unit-input-row { display: flex; align-items: center; gap: 6px; width: 100%; }
.unit-text { font-size: 13px; color: #606266; flex-shrink: 0; white-space: nowrap; }
</style>
