<template>
  <!-- 如果是单页模式，直接显示单页详情组件 -->
  <DefaultSingle v-if="isSinglePage" />
  <div v-else class="page">
    <!-- 头部，与 AI 智能体列表一致的结构 -->
    <div class="page-header">
      <div class="header-left">
        <h2>{{ t(title) }}</h2>
      </div>
      <div class="header-right">
        <!-- 工具栏覆盖组件 - 支持两种接口：context 或 props -->
        <component
          v-if="toolbarComponent"
          :is="toolbarComponent"
          :context="{
            entity,
            filters,
            searchQuery,
            viewMode,
            selectedKeys,
            loading,
            rows,
            reload,
            createRecordHandler,
            handleDeleteSelected,
            router,
            t,
            canEdit: canEditList,
          }"
          :entity="entity"
          :search-query="searchQuery"
          :view-mode="viewMode"
          :selected-keys="selectedKeys"
          :loading="loading"
          @update:search-query="searchQuery = $event"
          @update:view-mode="viewMode = $event"
          @reload="reload"
          @create="createRecordHandler"
          @delete-selected="handleDeleteSelected"
        />
        <DefaultListToolbar
          v-else
          :entity="entity"
          :search-query="searchQuery"
          :view-mode="viewMode"
          :selected-keys="selectedKeys"
          :loading="loading"
          :can-edit="canEditList"
          @update:search-query="searchQuery = $event"
          @update:view-mode="viewMode = $event"
          @reload="reload"
          @create="createRecordHandler"
          @delete-selected="handleDeleteSelected"
        />
      </div>
    </div>

    <div class="page-content">
      <!-- 过滤栏覆盖组件 - 支持两种接口：context 或 props -->
      <component
        v-if="filterBarComponent"
        :is="filterBarComponent"
        :context="{
          fields: metaFields,
          filters,
          onFilterChange
        }"
        :fields="metaFields"
        v-model:filters="filters"
        @filter-change="onFilterChange"
      />
      <!-- 默认过滤栏 -->
      <DefaultListFilterBar 
        v-else-if="!isSinglePage && metaFields.length > 0"
        :fields="metaFields"
        v-model:filters="filters"
        @filter-change="onFilterChange"
      />

      <!-- 列表页优化：保留上次内容，显示轻微加载指示，提供更好的连续浏览体验 -->
      <div class="list-content-wrapper" :class="{ 'loading-state': loading }">
        <!-- 加载指示（不遮挡内容） -->
        <div v-if="loading && rows.length === 0" class="loading-full">
          <i class="fa fa-spinner fa-spin"></i> {{ t('Loading...') }}
        </div>
        <div v-else>
          <!-- 顶部轻微加载指示（仅在已有数据时显示） -->
          <div v-if="loading && rows.length > 0" class="loading-overlay">
            <i class="fa fa-spinner fa-spin"></i>
          </div>
          <!-- 卡片视图 -->
          <div v-if="viewMode === 'card'" class="agent-grid">
          <div 
            v-for="row in filteredRows" 
            :key="row.name" 
            class="agent-card" 
            :class="{ selected: selectedKeys.includes(row.name) }"
            @click="openDetail(row.name)"
          >
            <div class="card-checkbox">
              <input 
                type="checkbox" 
                :checked="selectedKeys.includes(row.name)"
                @click.stop="toggleSelection(row.name)"
              />
            </div>
            <!-- 卡片图片 -->
            <div v-if="imageFieldName && getImageUrl(row) && !cardImageLoadErrors.has(row.name)" class="card-image">
              <img 
                :src="getImageUrl(row) || ''" 
                :alt="row[primaryLabel] || row.name"
                @error="(e) => handleCardImageError(e, row.name)"
                @load="(e) => handleCardImageLoad(e, row.name)"
              />
            </div>
            <div class="card-content">
              <div class="info" @click.stop="openDetail(row.name)">
                <div class="title">{{ row[primaryLabel] || row.name }}</div>
                <div class="desc">{{ row.name }}</div>
                <div class="meta">
                  <template v-for="f in cardBadges" :key="f.key">
                    <!-- Select字段使用独立的span，不包裹在.badge中 -->
                    <span 
                      v-if="isSelectField(f.key) && row[f.key] !== null && row[f.key] !== undefined && row[f.key] !== ''"
                      class="select-badge" 
                      :style="{ 
                        backgroundColor: getSelectBadgeColor(f.key, row[f.key]),
                        color: getSelectBadgeTextColor(f.key, row[f.key])
                      }"
                    >
                      {{ formatDisplayValue(row[f.key], f.key) }}
                    </span>
                    <!-- 其他字段使用.badge包裹，只在有值时渲染 -->
                    <span v-else-if="row[f.key] !== null && row[f.key] !== undefined && row[f.key] !== ''" class="badge">
                      <template v-if="isBooleanField(f.key) && (row[f.key] === 1 || row[f.key] === 0 || typeof row[f.key] === 'boolean')">
                        <span v-if="row[f.key] === 1 || row[f.key] === true" class="boolean-true">✓</span>
                        <span v-else class="boolean-false">○</span>
                      </template>
                      <template v-else-if="isIconField(f.key) && row[f.key]">
                        <Icon :icon="row[f.key]" :width="20" :height="20" class="icon-gray" />
                      </template>
                      <template v-else>{{ formatDisplayValue(row[f.key], f.key) }}</template>
                    </span>
                  </template>
                </div>
              </div>
            </div>
            <!-- 操作列覆盖组件（卡片视图） - 支持两种接口：context 或 props -->
            <component
              v-if="actionsComponent"
              :is="actionsComponent"
              :context="{
                row,
                entity,
                openDetail,
                editRecord,
                deleteRecord,
                router,
                t,
                viewMode: 'card'
              }"
              :row="row"
              :entity="entity"
              view-mode="card"
              @view="openDetail(row.name)"
              @edit="editRecord(row)"
              @delete="deleteRecord(row.name)"
            />
            <!-- 默认操作按钮 -->
            <DefaultListActions
              v-else
              :row="row"
              :entity="entity"
              view-mode="card"
              @view="openDetail(row.name)"
              @edit="editRecord(row)"
              @delete="deleteRecord(row.name)"
            />
          </div>
          </div>
          <div v-if="viewMode === 'card'" class="list-pagination">
            <n-pagination v-model:page="page" :page-count="pageCount" size="small" />
          </div>

          <!-- 列表视图 -->
          <div v-else class="agent-list" :class="{ 'has-image': imageFieldName }">
          <div class="list-header">
            <div class="col-checkbox">
              <input
                type="checkbox"
                :checked="selectedKeys.length === filteredRows.length && filteredRows.length > 0"
                :indeterminate="selectedKeys.length > 0 && selectedKeys.length < filteredRows.length"
                @change="toggleSelectAll"
              />
            </div>
            <!-- 列表图片列 -->
            <div v-if="imageFieldName" class="col-image">{{ t('Image') }}</div>
            <div v-for="col in displayColumns" :key="col.key" :class="`col-${col.key}`">{{ t(col.title) }}</div>
            <div class="col-actions">{{ t('Actions') }}</div>
          </div>
          <div class="list-body">
            <div
              v-for="row in filteredRows"
              :key="row.name"
              class="list-item"
              :class="{ selected: selectedKeys.includes(row.name) }"
              @click="openDetail(row.name)"
            >
              <div class="col-checkbox">
                <input
                  type="checkbox"
                  :checked="selectedKeys.includes(row.name)"
                  @click.stop="toggleSelection(row.name)"
                />
              </div>
              <!-- 列表图片 -->
              <div v-if="imageFieldName" class="col-image" @click.stop="openDetail(row.name)">
                <img 
                  v-if="getImageUrl(row) && !imageLoadErrors.has(row.name)" 
                  :src="getImageUrl(row) || ''" 
                  :alt="row[primaryLabel] || row.name"
                  @error="(e) => handleImageError(e, row.name)"
                  @load="(e) => handleImageLoad(e, row.name)"
                />
                <span v-else class="image-placeholder">—</span>
              </div>
              <div v-for="col in displayColumns" :key="col.key" :class="`col-${col.key}`" @click.stop="openDetail(row.name)">
                <template v-if="isBooleanField(col.key) && (row[col.key] === 1 || row[col.key] === 0 || typeof row[col.key] === 'boolean')">
                  <span v-if="row[col.key] === 1 || row[col.key] === true" class="boolean-true">✓</span>
                  <span v-else class="boolean-false">○</span>
                </template>
                <template v-else-if="isIconField(col.key) && row[col.key]">
                  <Icon :icon="row[col.key]" :width="20" :height="20" class="icon-gray" />
                </template>
                <template v-else-if="isSelectField(col.key) && row[col.key] !== null && row[col.key] !== undefined && row[col.key] !== ''">
                  <span 
                    class="select-badge" 
                    :style="{ 
                      backgroundColor: getSelectBadgeColor(col.key, row[col.key]),
                      color: getSelectBadgeTextColor(col.key, row[col.key])
                    }"
                  >
                    {{ formatDisplayValue(row[col.key], col.key) }}
                  </span>
                </template>
                <template v-else-if="row[col.key] !== null && row[col.key] !== undefined && row[col.key] !== ''">{{ formatDisplayValue(row[col.key], col.key) }}</template>
              </div>
              <!-- 操作列覆盖组件 - 支持两种接口：context 或 props -->
              <component
                v-if="actionsComponent"
                :is="actionsComponent"
                :context="{
                  row,
                  entity,
                  openDetail,
                  editRecord,
                  deleteRecord,
                  router,
                  t,
                  viewMode: 'list'
                }"
                :row="row"
                :entity="entity"
                view-mode="list"
                @view="openDetail(row.name)"
                @edit="editRecord(row)"
                @delete="deleteRecord(row.name)"
              />
              <!-- 默认操作按钮 -->
              <DefaultListActions
                v-else
                :row="row"
                :entity="entity"
                view-mode="list"
                @view="openDetail(row.name)"
                @edit="editRecord(row)"
                @delete="deleteRecord(row.name)"
              />
            </div>
          </div>
          <div v-if="viewMode === 'list'" class="list-pagination">
            <n-pagination v-model:page="page" :page-count="pageCount" size="small" />
          </div>
        </div>
        </div>
      </div>
    </div>
  </div>
  
  <!-- 创建PageType模态对话框 -->
  <n-modal
    v-model:show="showCreateModal"
    preset="dialog"
    :title="t('Create PageType')"
    :positive-text="t('Create and Continue')"
    :negative-text="t('Cancel')"
    :loading="creating"
    @positive-click="handleCreatePageType"
    style="width: 600px"
  >
    <div style="padding: 16px 0">
      <!-- 第一行：名称、扩展包、模块 -->
      <div style="display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 12px; margin-bottom: 16px">
        <div>
          <div style="margin-bottom: 6px; font-weight: 500; color: #374151; font-size: 13px">
            {{ t('Name') }} <span style="color: #ef4444">*</span>
          </div>
          <n-input
            v-model:value="newPageTypeName"
            :placeholder="t('Enter name')"
            :disabled="creating"
            size="small"
          />
        </div>
        <div>
          <div style="margin-bottom: 6px; font-weight: 500; color: #374151; font-size: 13px">
            {{ t('Extends') }}
          </div>
          <n-select
            v-model:value="newPageTypeExtends"
            :options="packageOptions"
            :placeholder="t('Enter extends')"
            :disabled="creating"
            :loading="loadingPackages"
            filterable
            clearable
            size="small"
            :show-arrow="false"
            class="no-dropdown-icon"
          />
        </div>
        <div>
          <div style="margin-bottom: 6px; font-weight: 500; color: #374151; font-size: 13px">
            {{ t('Module') }} <span style="color: #ef4444">*</span>
          </div>
          <n-select
            v-model:value="newPageTypeModule"
            :options="moduleOptions"
            :placeholder="t('Enter module')"
            :disabled="creating"
            :loading="loadingModules"
            filterable
            clearable
            size="small"
            :show-arrow="false"
            class="no-dropdown-icon"
          />
        </div>
      </div>
      
      <!-- 复选框选项 -->
      <div style="display: flex; flex-direction: column; gap: 12px">
        <div style="display: flex; align-items: flex-start">
          <n-checkbox v-model:checked="newPageTypeIsSubmittable" :disabled="creating" size="small">
            <span style="font-size: 13px">{{ t('Is Submittable') }}</span>
          </n-checkbox>
        </div>
        <div style="font-size: 12px; color: #6b7280; margin-top: -8px; margin-left: 24px">
          {{ t('Submittable documents can be submitted and modified, can only be modified or deleted after submission') }}
        </div>
        
        <div style="display: flex; align-items: flex-start">
          <n-checkbox v-model:checked="newPageTypeIsChild" :disabled="creating" size="small">
            <span style="font-size: 13px">{{ t('Is Child Table') }}</span>
          </n-checkbox>
        </div>
        <div style="font-size: 12px; color: #6b7280; margin-top: -8px; margin-left: 24px">
          {{ t('Child table will be displayed in the form of table collection in the parent PageType') }}
        </div>
        
        <div style="display: flex; align-items: flex-start">
          <n-checkbox v-model:checked="newPageTypeIsSingle" :disabled="creating" size="small">
            <span style="font-size: 13px">{{ t('Is Single') }}</span>
          </n-checkbox>
        </div>
        <div style="font-size: 12px; color: #6b7280; margin-top: -8px; margin-left: 24px">
          {{ t('Single type has only one record, without name field, saved in tabSingles') }}
        </div>
        
        <div style="display: flex; align-items: flex-start">
          <n-checkbox v-model:checked="newPageTypeIsTree" :disabled="creating" size="small">
            <span style="font-size: 13px">{{ t('Is Tree') }}</span>
          </n-checkbox>
        </div>
        <div style="font-size: 12px; color: #6b7280; margin-top: -8px; margin-left: 24px">
          {{ t('Tree structure uses parent node collection for nested display') }}
        </div>
        
        <div style="display: flex; align-items: flex-start">
          <n-checkbox v-model:checked="newPageTypeIsVirtual" :disabled="creating" size="small">
            <span style="font-size: 13px">{{ t('Is Virtual') }}</span>
          </n-checkbox>
        </div>
        
        <div style="display: flex; align-items: flex-start">
          <n-checkbox v-model:checked="newPageTypeIsTable" :disabled="creating" size="small">
            <span style="font-size: 13px">{{ t('Is Table') }}</span>
          </n-checkbox>
        </div>
      </div>
      
      <!-- 提示信息 -->
      <div style="margin-top: 16px; padding: 8px 12px; background: #f0f9ff; border-radius: 6px; font-size: 12px; color: #0369a1">
        {{ t('The system will automatically generate a friendly URL based on the name') }}
      </div>
    </div>
  </n-modal>
</template>

<script setup lang="ts">
import { onMounted, ref, computed, watch, shallowRef, markRaw } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import { NPagination, NModal, NInput, NButton, NCheckbox, NSelect, useMessage, useDialog } from 'naive-ui'
import { Icon } from '@iconify/vue'
import axios from 'axios'
import { t } from '@/shared/i18n'
import { usePageTypeSlug } from '@/shared/utils/slug'
import { isSinglePageType } from '@/shared/utils/pagetype'
import DefaultSingle from '@/core/pagetype/default_single.vue'
import DefaultListToolbar from '@/core/pagetype/default_list_toolbar.vue'
import DefaultListFilterBar from '@/core/pagetype/default_list_filterbar.vue'
import DefaultListActions from '@/core/pagetype/default_list_actions.vue'
import {
  resolvePagetypeListToolbarOverride,
  resolvePagetypeListFilterBarOverride,
  resolvePagetypeListActionsOverride
} from '@/core/registry/pagetypeOverride'
import { downloadImageToLocal } from '@/shared/api/common'
import { usePermissionStore } from '@/shared/stores/permissions'

const route = useRoute()
const router = useRouter()
const message = useMessage()
const dialog = useDialog()
const permissionStore = usePermissionStore()

// 使用组合式函数处理URL slug
const { pagetypeSlug, entity } = usePageTypeSlug(route)
const title = computed(() => entity.value)
const canEditList = computed(() => permissionStore.canWrite(entity.value))

// 覆盖组件引用（子组件覆盖，整体覆盖由 ListPage.vue 处理）
const toolbarComponent = shallowRef<any | null>(null)
const filterBarComponent = shallowRef<any | null>(null)
const actionsComponent = shallowRef<any | null>(null)

// 检查是否为单页模式
const isSinglePage = ref(false)
const searchQuery = ref('')
const loading = ref(false)
const rows = ref<any[]>([])
const page = ref(1)
const pageSize = ref(parseInt(localStorage.getItem('itemsPerPage') || '10'))
const pageCount = computed(() => {
  // 确保有总数数据时才计算分页
  if (total.value === 0 || rows.value.length === 0) return 1
  return Math.max(1, Math.ceil(total.value / pageSize.value))
})
const total = ref(0)
const selectedKeys = ref<string[]>([])
const viewMode = ref<'card' | 'list'>(
  (localStorage.getItem(`genericListViewMode:${entity.value}`) as 'card' | 'list') || 'list'
)

// 过滤条件
const filters = ref<Record<string, any>>({})

// PageType创建对话框
const showCreateModal = ref(false)
const newPageTypeName = ref('')
const newPageTypeModule = ref('')
const newPageTypeExtends = ref('')
const newPageTypeIsSubmittable = ref(false)
const newPageTypeIsChild = ref(false)
const newPageTypeIsSingle = ref(false)
const newPageTypeIsTree = ref(false)
const newPageTypeIsVirtual = ref(false)
const newPageTypeIsTable = ref(false)
const creating = ref(false)

// 模块和扩展包选项
const moduleOptions = ref<Array<{label: string; value: string}>>([])
const packageOptions = ref<Array<{label: string; value: string}>>([])
const loadingModules = ref(false)
const loadingPackages = ref(false)

// 监听过滤条件变化
function onFilterChange() {
  page.value = 1 // 重置到第一页
  loadData()
}

const displayColumns = computed(() => {
  // 生成列表列：严格使用 in_list_view 属性，排除分隔类
  const isDisplayable = (f: any) => !['Section Break', 'Column Break', 'Tab Break'].includes(f.fieldtype)
  const display = metaFields.value.filter((f: any) => f.in_list_view && isDisplayable(f))
  
  // 不再回退到显示所有字段，如果没有设置 in_list_view，则只显示 name
  const cols: any[] = display.slice(0, 30).map((f: any) => ({ title: f.label || f.fieldname, key: f.fieldname }))
  
  // 确保有 name 列
  if (!cols.find(c => c.key === 'name')) cols.unshift({ title: 'ID', key: 'name' })
  return cols
})

const primaryLabel = computed(() => {
  const f = metaFields.value.find((x: any) => x.in_list_view && x.fieldname !== 'name')
  return f?.fieldname || 'name'
})
const cardBadges = computed(() => {
  // 显示所有 displayColumns 中的字段，除了已经显示的 primaryLabel 和 name
  const keys = displayColumns.value.map((c: any) => c.key).filter((k: string) => k && k !== 'actions' && k !== primaryLabel.value && k !== 'name')
  return keys.map((k: string) => ({ key: k }))
})

// 获取图片字段名
const imageFieldName = computed(() => {
  return pageMeta.value?.image_field || ''
})

// 获取图片URL
function getImageUrl(row: any): string | null {
  if (!imageFieldName.value) return null
  const imageValue = row[imageFieldName.value]
  if (!imageValue) return null
  
  // 处理字符串类型
  if (typeof imageValue === 'string') {
    const trimmed = imageValue.trim()
    return trimmed || null
  }
  
  // 处理可能被序列化为对象的字段值
  if (typeof imageValue === 'object') {
    // 尝试从对象中提取URL
    const url = imageValue.file_url || imageValue.url || imageValue.value || imageValue
    if (typeof url === 'string' && url.trim()) {
      return url.trim()
    }
  }
  
  return null
}

// 图片加载错误处理（列表视图）
const imageLoadErrors = ref<Set<string>>(new Set())

function handleImageError(event: Event, rowName: string) {
  const img = event.target as HTMLImageElement
  imageLoadErrors.value.add(rowName)
  console.warn('[ListPage] Image load failed:', {
    rowName,
    src: img.src,
    imageField: imageFieldName.value,
    rowData: rows.value.find((r: any) => r.name === rowName)?.[imageFieldName.value]
  })
}

function handleImageLoad(_event: Event, rowName: string) {
  imageLoadErrors.value.delete(rowName)
}

// 图片加载错误处理（卡片视图）
const cardImageLoadErrors = ref<Set<string>>(new Set())

function handleCardImageError(event: Event, rowName: string) {
  const img = event.target as HTMLImageElement
  cardImageLoadErrors.value.add(rowName)
  console.warn('[ListPage] Card image load failed:', {
    rowName,
    src: img.src,
    imageField: imageFieldName.value,
    rowData: rows.value.find((r: any) => r.name === rowName)?.[imageFieldName.value]
  })
}

function handleCardImageLoad(_event: Event, rowName: string) {
  cardImageLoadErrors.value.delete(rowName)
}

// 自动下载图片的函数（与详情页一致）
async function autoDownloadImages(imageUrls: string[]) {
  const downloadPromises = imageUrls.map(async (url) => {
    const filename = url.split('/').pop() || 'image.jpg'
    
    try {
      const result = await downloadImageToLocal(url, filename)
      if (result.success) {
        // 返回是否是新下载的图片（非缓存）
        return !(result as any).data?.cached
      }
    } catch (error) {
      // 静默失败，不影响界面
    }
    return false
  })
  
  await Promise.all(downloadPromises)
}

const metaFields = ref<any[]>([])
const pageMeta = ref<any>({})
const linkTitleCache = ref<Record<string, string>>({})
const pageTypeConfigCache = ref<Record<string, any>>({})
const cacheAccessOrder = ref<string[]>([]) // 记录访问顺序，用于LRU
let saveCacheTimer: ReturnType<typeof setTimeout> | null = null
const CACHE_EXPIRY_DAYS = 7 // 缓存过期天数
const MAX_CACHE_SIZE = 500 // 最大缓存条目数

// 从localStorage恢复缓存（避免刷新时抖动）
function loadCacheFromStorage() {
  try {
    const cached = localStorage.getItem('linkTitleCache')
    if (cached) {
      const parsed = JSON.parse(cached)
      const { data, timestamp } = parsed
      
      // 检查是否过期
      const now = Date.now()
      const expiryTime = CACHE_EXPIRY_DAYS * 24 * 60 * 60 * 1000
      if (timestamp && now - timestamp < expiryTime && data) {
        // 合并到当前缓存，但不覆盖已有值
        Object.keys(data).forEach(key => {
          if (!linkTitleCache.value[key]) {
            linkTitleCache.value[key] = data[key]
            // 恢复访问顺序
            if (!cacheAccessOrder.value.includes(key)) {
              cacheAccessOrder.value.push(key)
            }
          }
        })
      }
    }
  } catch (error) {
    console.error('加载缓存失败:', error)
  }
}

// 更新缓存并记录访问顺序（LRU策略）
function updateCacheWithLRU(key: string, value: string) {
  // 如果已存在，更新访问顺序
  if (linkTitleCache.value[key]) {
    const index = cacheAccessOrder.value.indexOf(key)
    if (index > -1) {
      cacheAccessOrder.value.splice(index, 1)
    }
  }
  
  // 如果缓存已满，移除最久未使用的
  if (cacheAccessOrder.value.length >= MAX_CACHE_SIZE && !linkTitleCache.value[key]) {
    const oldestKey = cacheAccessOrder.value.shift()
    if (oldestKey) {
      delete linkTitleCache.value[oldestKey]
    }
  }
  
  // 添加/更新缓存
  linkTitleCache.value[key] = value
  cacheAccessOrder.value.push(key)
}

// 保存缓存到localStorage（带防抖，页面关闭时立即保存）
function saveCacheToStorage() {
  if (saveCacheTimer) {
    clearTimeout(saveCacheTimer)
  }
  saveCacheTimer = setTimeout(() => {
    saveCacheImmediately()
  }, 500) // 减少防抖时间到500ms，更快响应
}

// 立即保存缓存（用于页面关闭时）
function saveCacheImmediately() {
  if (saveCacheTimer) {
    clearTimeout(saveCacheTimer)
    saveCacheTimer = null
  }
  
  try {
    // 按访问顺序限制缓存大小
    if (cacheAccessOrder.value.length > MAX_CACHE_SIZE) {
      const toRemove = cacheAccessOrder.value.slice(0, cacheAccessOrder.value.length - MAX_CACHE_SIZE)
      toRemove.forEach(key => {
        delete linkTitleCache.value[key]
      })
      cacheAccessOrder.value = cacheAccessOrder.value.slice(-MAX_CACHE_SIZE)
    }
    
    // 保存带时间戳的缓存
    localStorage.setItem('linkTitleCache', JSON.stringify({
      data: linkTitleCache.value,
      timestamp: Date.now()
    }))
  } catch (error) {
    // 如果存储空间不足，清理旧缓存
    if (error instanceof DOMException && error.code === 22) {
      try {
        localStorage.removeItem('linkTitleCache')
        // 重试保存，只保存最近100个
        const recentKeys = cacheAccessOrder.value.slice(-100)
        const recentCache: Record<string, string> = {}
        recentKeys.forEach(key => {
          recentCache[key] = linkTitleCache.value[key]
        })
        localStorage.setItem('linkTitleCache', JSON.stringify({
          data: recentCache,
          timestamp: Date.now()
        }))
        linkTitleCache.value = recentCache
        cacheAccessOrder.value = recentKeys
      } catch (e) {
        console.error('保存缓存失败:', e)
      }
    } else {
      console.error('保存缓存失败:', error)
    }
  }
}

// 页面关闭时立即保存缓存
if (typeof window !== 'undefined') {
  window.addEventListener('beforeunload', saveCacheImmediately)
  window.addEventListener('pagehide', saveCacheImmediately)
}

async function loadMeta() {
  loading.value = true
  try {
    const url = `/api/data/PageType/${encodeURIComponent(entity.value)}`
    const res = await axios.get(url)
    const data = res.data?.data || {}
    metaFields.value = data.fields || []
    pageMeta.value = data // 保存完整的pageMeta，包含image_field等配置
    
    // 检查是否为单页模式（直接使用已加载的数据，避免重复请求）
    isSinglePage.value = Boolean(data.issingle === 1 || data.issingle === true)
    
    // 加载缓存的Link标题（刷新时减少抖动）
    loadCacheFromStorage()
  } finally {
    loading.value = false
  }
}

// 获取页面类型配置
async function getPageTypeConfig(pagetype: string) {
  if (!pagetype) return {}
  
  // 检查缓存
  if (pageTypeConfigCache.value[pagetype]) {
    return pageTypeConfigCache.value[pagetype]
  }
  
  try {
    const response = await axios.get(`/api/data/PageType/${encodeURIComponent(pagetype)}`)
    
    const config = response.data?.data || {}
    pageTypeConfigCache.value[pagetype] = config
    return config
  } catch (error) {
    console.error('获取页面类型配置失败:', error)
    return {}
  }
}

// 预加载Link字段的title_field值（优化：按pagetype分组批量请求）
async function preloadLinkTitles() {
  // 找到所有Link类型的字段
  const linkFields = metaFields.value.filter(f => f.fieldtype === 'Link' && f.options)
  
  if (linkFields.length === 0) return
  
  // 按pagetype分组收集需要加载的记录名，使用Map去重
  const pagetypeGroups = new Map<string, Set<string>>()
  
  rows.value.forEach(row => {
    linkFields.forEach(field => {
      const value = row[field.fieldname]
      if (value) {
        const pagetype = field.options
        if (!pagetypeGroups.has(pagetype)) {
          pagetypeGroups.set(pagetype, new Set())
        }
        pagetypeGroups.get(pagetype)!.add(value)
      }
    })
  })
  
  // 按pagetype批量加载（优化：每组使用一次API调用）
  await Promise.all(
    Array.from(pagetypeGroups.entries()).map(async ([pagetype, recordNames]) => {
      // 先获取配置，检查是否需要加载title_field
      const config = await getPageTypeConfig(pagetype)
      const titleField = config.title_field || 'name'
      const showTitleFieldInLink = config.show_title_field_in_link || false
      
      // 如果标题字段就是name或未启用show_title_field_in_link，直接缓存
      if (titleField === 'name' || !showTitleFieldInLink) {
        recordNames.forEach(name => {
          const cacheKey = `${pagetype}_${name}`
          if (!linkTitleCache.value[cacheKey]) {
            updateCacheWithLRU(cacheKey, name)
          }
        })
        return
      }
      
      // 批量获取记录（使用列表API，通过filters传入多个name）
      const namesToLoad = Array.from(recordNames).filter(name => {
        const cacheKey = `${pagetype}_${name}`
        return !linkTitleCache.value[cacheKey]
      })
      
      if (namesToLoad.length === 0) return
      
      try {
        // 使用列表API批量获取（name in [...]）
        const filters = [['name', 'in', namesToLoad]]
        const fields = ['name', titleField]
        const result = await axios.get(`/api/data/${encodeURIComponent(pagetype)}`, {
          params: {
            fields: JSON.stringify(fields),
            filters: JSON.stringify(filters),
            limit_page_length: namesToLoad.length
          }
        })
        
        // 缓存结果（使用LRU策略）
        const records = result.data?.data || []
        records.forEach((record: any) => {
          const name = record.name
          const titleValue = record[titleField] || name
          const cacheKey = `${pagetype}_${name}`
          updateCacheWithLRU(cacheKey, titleValue)
        })
        
        // 对于API未返回的记录，缓存原值（可能是已删除的记录）
        namesToLoad.forEach(name => {
          const cacheKey = `${pagetype}_${name}`
          if (!linkTitleCache.value[cacheKey]) {
            updateCacheWithLRU(cacheKey, name)
          }
        })
        
        // 保存到localStorage（防抖，避免频繁写入）
        saveCacheToStorage()
      } catch (error) {
        console.error(`批量加载${pagetype}的标题失败:`, error)
        // 失败时缓存原值
        namesToLoad.forEach(name => {
          const cacheKey = `${pagetype}_${name}`
          if (!linkTitleCache.value[cacheKey]) {
            updateCacheWithLRU(cacheKey, name)
          }
        })
      }
    })
  )
}

async function loadData() {
  loading.value = true
  try {
    const listUrl = `/api/data/${encodeURIComponent(entity.value)}`
    // 仅请求所需字段，避免接口默认不返回
    let fieldNames = displayColumns.value.map((c: any) => c.key).filter((k: string) => k && k !== 'actions')
    // 如果配置了image_field，确保包含该字段
    if (imageFieldName.value && !fieldNames.includes(imageFieldName.value)) {
      fieldNames.push(imageFieldName.value)
    }
    
    // 构建过滤参数
    const params: any = { 
      fields: JSON.stringify(fieldNames), 
      limit_start: (page.value - 1) * pageSize.value, 
      limit_page_length: pageSize.value,
      order_by: 'modified desc'
    }
    
    // 添加过滤条件
    const filterConditions: any[] = []
    
    // 先处理非Link字段的过滤条件
    const linkFieldFilters: Array<{ fieldName: string; value: string; fieldMeta: any }> = []
    
    Object.entries(filters.value).forEach(([fieldName, value]) => {
      if (value !== null && value !== undefined && value !== '' && 
          !(Array.isArray(value) && value.length === 0)) {
        if (Array.isArray(value)) {
          // 多选字段使用 in 操作符
          filterConditions.push([fieldName, 'in', value])
        } else {
          // 根据字段类型选择操作符
          const fieldMeta = metaFields.value.find(f => f.fieldname === fieldName)
          const fieldType = fieldMeta?.fieldtype || ''
          
          // 特殊处理：name字段（ID）始终使用模糊搜索
          if (fieldName === 'name' && typeof value === 'string') {
            filterConditions.push([fieldName, 'like', `%${value}%`])
          }
          // Link字段类型：需要同时匹配字段值和title_field
          else if (fieldType === 'Link' && typeof value === 'string' && fieldMeta?.options) {
            // 收集Link字段过滤条件，稍后处理
            linkFieldFilters.push({ fieldName, value: value as string, fieldMeta })
          } else if (['Data', 'Text', 'Long Text', 'Comment'].includes(fieldType)) {
            // 文本类型字段使用 like 操作符进行模糊搜索
            if (typeof value === 'string') {
              filterConditions.push([fieldName, 'like', `%${value}%`])
            }
          } else {
            // 其他类型字段使用精确匹配
            filterConditions.push([fieldName, '=', value])
          }
        }
      }
    })
    
    // 处理Link字段的过滤：需要搜索关联记录的title_field
    for (const linkFilter of linkFieldFilters) {
      const { fieldName, value, fieldMeta } = linkFilter
      const linkedPagetype = fieldMeta.options
      
      try {
        // 获取关联pagetype的配置
        const config = await getPageTypeConfig(linkedPagetype)
        const titleField = config.title_field || 'name'
        
        // 构建匹配的name值列表
        const matchedNames = new Set<string>()
        
        // 1. 先匹配Link字段值（name字段）本身
        if (value) {
          matchedNames.add(value) // 精确匹配
          // 也支持模糊匹配name字段
        }
        
        // 2. 如果title_field不是name且启用了show_title_field_in_link，搜索title_field
        if (titleField !== 'name' && config.show_title_field_in_link) {
          try {
            // 搜索关联pagetype的title_field
            const searchFilters = [[titleField, 'like', `%${value}%`]]
            const searchResult = await axios.get(`/api/data/${encodeURIComponent(linkedPagetype)}`, {
              params: {
                fields: JSON.stringify(['name']),
                filters: JSON.stringify(searchFilters),
                limit_page_length: 100 // 限制最多100条，避免性能问题
              }
            })
            
            const matchedRecords = searchResult.data?.data || []
            matchedRecords.forEach((record: any) => {
              if (record.name) {
                matchedNames.add(record.name)
              }
            })
          } catch (error) {
            console.warn(`搜索${linkedPagetype}的title_field失败:`, error)
          }
        } else if (titleField === 'name') {
          // 如果title_field就是name，直接使用like匹配
          // 使用OR条件：匹配name本身或name字段like
          // 由于后端可能不支持OR，我们使用in操作符，包含value和可能的匹配值
          // 先搜索匹配的记录
          try {
            const searchFilters = [['name', 'like', `%${value}%`]]
            const searchResult = await axios.get(`/api/data/${encodeURIComponent(linkedPagetype)}`, {
              params: {
                fields: JSON.stringify(['name']),
                filters: JSON.stringify(searchFilters),
                limit_page_length: 100
              }
            })
            
            const matchedRecords = searchResult.data?.data || []
            matchedRecords.forEach((record: any) => {
              if (record.name) {
                matchedNames.add(record.name)
              }
            })
          } catch (error) {
            console.warn(`搜索${linkedPagetype}的name字段失败:`, error)
          }
        }
        
        // 如果有匹配的name值，使用in操作符
        if (matchedNames.size > 0) {
          filterConditions.push([fieldName, 'in', Array.from(matchedNames)])
        } else {
          // 如果没有匹配值，使用like匹配字段值本身
          filterConditions.push([fieldName, 'like', `%${value}%`])
        }
      } catch (error) {
        console.warn(`处理Link字段${fieldName}过滤失败，使用字段值匹配:`, error)
        // 降级方案：直接使用like匹配字段值
        filterConditions.push([fieldName, 'like', `%${value}%`])
      }
    }
    
    if (filterConditions.length > 0) {
      params.filters = JSON.stringify(filterConditions)
    }
    
    const res = await axios.get(listUrl, { 
      params
    })
    rows.value = res.data?.data || []
    // 后端可能没有返回 total，我们基于第一次请求的数量来估计
    // 如果当前页数据不足 pageSize，说明是最后一页
    if (!res.data?.total) {
      if (res.data?.data?.length < pageSize.value) {
        // 最后一页的情况：total = (page-1) * pageSize + 当前页实际数量
        total.value = (page.value - 1) * pageSize.value + res.data?.data?.length
      } else {
        // 可能还有更多数据，设置一个较大的值确保分页组件工作
        total.value = page.value * pageSize.value + 1
      }
    } else {
      total.value = res.data.total
    }
    
    // 预加载Link字段的title_field值（在loading期间同步执行，避免抖动）
    await preloadLinkTitles()
    
    // 自动下载图片到本地（异步执行，不阻塞界面渲染）
    if (imageFieldName.value && rows.value.length > 0) {
      const imageUrls: string[] = []
      rows.value.forEach((row: any) => {
        const imageUrl = getImageUrl(row)
        if (imageUrl && imageUrl.startsWith('/files/')) {
          imageUrls.push(imageUrl)
        }
      })
      
      if (imageUrls.length > 0) {
        // 异步下载，不阻塞界面渲染
        autoDownloadImages(imageUrls).catch((error: any) => {
          console.warn('列表页图片下载失败:', error)
        })
      }
    }
  } catch (error) {
    console.error('Load data error:', error)
    message.error(t('Load failed'))
  } finally {
    loading.value = false
  }
}

onMounted(async () => {
  // 解析子组件覆盖（工具栏、过滤栏、操作栏）
  const listToolbarComp = await resolvePagetypeListToolbarOverride(pagetypeSlug.value)
  toolbarComponent.value = listToolbarComp ? markRaw(listToolbarComp) : null
  
  const listFilterBarComp = await resolvePagetypeListFilterBarOverride(pagetypeSlug.value)
  filterBarComponent.value = listFilterBarComp ? markRaw(listFilterBarComp) : null
  
  const listActionsComp = await resolvePagetypeListActionsOverride(pagetypeSlug.value)
  actionsComponent.value = listActionsComp ? markRaw(listActionsComp) : null
  
  await loadMeta()
  // 只有在非单页模式下才加载列表数据
  if (!isSinglePage.value) {
    await loadData()
  }
})

// 监听分页变化
watch([page], () => {
  loadData()
})

// 监听路由参数变化，当entity变化时重新加载数据
watch(() => route.params.entity, async (newEntity, oldEntity) => {
  if (newEntity !== oldEntity) {
    // 重新解析子组件覆盖
    const listToolbarComp = await resolvePagetypeListToolbarOverride(String(newEntity))
    toolbarComponent.value = listToolbarComp ? markRaw(listToolbarComp) : null
    
    const listFilterBarComp = await resolvePagetypeListFilterBarOverride(String(newEntity))
    filterBarComponent.value = listFilterBarComp ? markRaw(listFilterBarComp) : null
    
    const listActionsComp = await resolvePagetypeListActionsOverride(String(newEntity))
    actionsComponent.value = listActionsComp ? markRaw(listActionsComp) : null
    
    // 重置分页和搜索
    page.value = 1
    searchQuery.value = ''
    selectedKeys.value = []
    filters.value = {}
    // 根据新entity重新加载视图模式（重要：修复全局生效的问题）
    viewMode.value = (localStorage.getItem(`genericListViewMode:${entity.value}`) as 'card' | 'list') || 'list'
    // 清空缓存（新entity使用新的缓存）
    linkTitleCache.value = {}
    // 重新加载元数据和数据
    await loadMeta() // loadMeta中会加载新entity的缓存
    // 只有在非单页模式下才加载列表数据
    if (!isSinglePage.value) {
      await loadData()
    }
  }
}, { immediate: false })

// 监听视图模式变化，保存到本地
watch(viewMode, (newMode) => {
  localStorage.setItem(`genericListViewMode:${entity.value}`, newMode)
})

function reload() {
  loadData()
}

const filteredRows = computed(() => {
  if (!searchQuery.value) return rows.value
  const q = searchQuery.value.toLowerCase()
  const keys = displayColumns.value.map((c: any) => c.key).filter((k: string) => k && k !== 'actions')
  return rows.value.filter((r: any) => keys.some((k: string) => String(r[k] ?? '').toLowerCase().includes(q)))
})

function toggleSelection(name: string) {
  const i = selectedKeys.value.indexOf(name)
  if (i > -1) selectedKeys.value.splice(i, 1)
  else selectedKeys.value.push(name)
}

function toggleSelectAll() {
  if (selectedKeys.value.length === filteredRows.value.length) {
    selectedKeys.value = []
  } else {
    selectedKeys.value = filteredRows.value.map(row => row.name)
  }
}

function openDetail(name: string) {
  router.push({ name: 'PageTypeDetail', params: { entity: pagetypeSlug.value, id: name } })
}

async function handleDeleteSelected() {
  if (selectedKeys.value.length === 0) return
  
  dialog.warning({
    title: t('Delete Selected Records'),
    content: `${t('Are you sure you want to delete')} ${selectedKeys.value.length} ${t('selected record(s)? This action cannot be undone.')}`,
    positiveText: t('Delete'),
    negativeText: t('Cancel'),
    onPositiveClick: async () => {
      loading.value = true
      try {
        const { deleteRecords } = await import('../../shared/api/common')
        const res = await deleteRecords(entity.value, selectedKeys.value)
        if (res.success) {
          message.success(res.message || t('Deleted successfully'))
          selectedKeys.value = []
          await loadData()
        } else {
          message.error(res.message || t('Delete failed'))
        }
      } catch (error) {
        message.error(t('Delete failed'))
        console.error('Delete error:', error)
      } finally {
        loading.value = false
      }
    }
  })
}

function createRecordHandler() {
  // 特殊处理：PageType需要先输入名称
  if (entity.value === 'PageType') {
    showCreatePageTypeDialog()
    return
  }
  
  // 普通记录：直接生成临时name并打开
  const randomStr = Math.random().toString(36).substring(2, 12)
  const tempName = `new-${pagetypeSlug.value}-${randomStr}`
  openDetail(tempName)
}

// 显示创建PageType对话框
function showCreatePageTypeDialog() {
  newPageTypeName.value = ''
  newPageTypeModule.value = ''
  newPageTypeExtends.value = ''
  newPageTypeIsSubmittable.value = false
  newPageTypeIsChild.value = false
  newPageTypeIsSingle.value = false
  newPageTypeIsTree.value = false
  newPageTypeIsVirtual.value = false
  newPageTypeIsTable.value = false
  showCreateModal.value = true
  
  // 加载模块和扩展包列表
  loadModules()
  loadPackages()
}

// 加载模块列表
async function loadModules() {
  if (moduleOptions.value.length > 0) return // 已加载过
  
  loadingModules.value = true
  try {
    // 使用与jingrow过滤栏相同的方式：调用 /api/data/Module Def
    const response = await axios.get('/api/data/Module Def', {
      params: {
        fields: JSON.stringify(['name']),
        order_by: 'name asc',
        limit_page_length: 1000
      }
    })
    
    const modules = response.data?.data || []
    moduleOptions.value = modules.map((m: any) => ({
      label: m.name,
      value: m.name
    }))
  } catch (error) {
    console.error('Load modules error:', error)
  } finally {
    loadingModules.value = false
  }
}

// 加载扩展包列表
async function loadPackages() {
  if (packageOptions.value.length > 0) return // 已加载过
  
  loadingPackages.value = true
  try {
    // 使用与jingrow过滤栏相同的方式：调用 /api/data/Package
    const response = await axios.get('/api/data/Package', {
      params: {
        fields: JSON.stringify(['name']),
        order_by: 'name asc',
        limit_page_length: 1000
      }
    })
    
    const packages = response.data?.data || []
    packageOptions.value = packages.map((p: any) => ({
      label: p.name,
      value: p.name
    }))
  } catch (error) {
    console.error('Load packages error:', error)
  } finally {
    loadingPackages.value = false
  }
}

// 创建PageType
async function handleCreatePageType() {
  if (!newPageTypeName.value.trim()) {
    message.error(t('Please enter PageType name'))
    return
  }
  
  if (!newPageTypeModule.value || !newPageTypeModule.value.trim()) {
    message.error(t('Please select module'))
    return
  }
  
  creating.value = true
  try {
    // 保持name原样（包含空格），与jingrow系统一致
    const inputName = newPageTypeName.value.trim()
    
    // 构建创建数据
    const createData: Record<string, any> = {
      name: inputName, // 保持原样，不转换空格
      module: newPageTypeModule.value.trim() // 必填
    }
    
    // 添加可选字段
    if (newPageTypeExtends.value && newPageTypeExtends.value.trim()) {
      createData.extends = newPageTypeExtends.value.trim()
    }
    if (newPageTypeIsSubmittable.value) {
      createData.is_submittable = 1
    }
    if (newPageTypeIsChild.value) {
      createData.is_child_table = 1
    }
    if (newPageTypeIsSingle.value) {
      createData.issingle = 1
    }
    if (newPageTypeIsTree.value) {
      createData.is_tree = 1
    }
    if (newPageTypeIsVirtual.value) {
      createData.is_virtual = 1
    }
    if (newPageTypeIsTable.value) {
      createData.istable = 1
    }
    
    console.log('[CreatePageType] 准备创建PageType:', inputName)
    console.log('[CreatePageType] 创建数据:', createData)
    
    const res = await axios.post(
      `/api/data/PageType`, createData)
    
    console.log('[CreatePageType] API响应:', res)
    console.log('[CreatePageType] 响应data:', res.data)
    console.log('[CreatePageType] 响应data.data:', res.data?.data)
    
    // 检查响应格式：res.data.data 应该包含创建的记录
    if (res.data?.data) {
      const createdRecord = res.data.data
      const recordName = createdRecord.name || inputName
      
      console.log('[CreatePageType] 创建成功，记录名称:', recordName)
      message.success(t('Created successfully'))
      showCreateModal.value = false
      
      // 跳转到新创建的PageType详情页
      openDetail(recordName)
    } else {
      console.error('[CreatePageType] 响应数据格式异常:', res.data)
      message.error(t('Create failed') + ': ' + t('Invalid response format'))
    }
  } catch (error: any) {
    console.error('[CreatePageType] 创建失败:', error)
    console.error('[CreatePageType] 错误详情:', error?.response?.data)
    const errorMsg = error?.response?.data?.detail || error?.response?.data?.message || error?.message || t('Create failed')
    message.error(errorMsg)
  } finally {
    creating.value = false
  }
}

function editRecord(row: any) {
  openDetail(row.name)
}

async function deleteRecord(name: string) {
  dialog.warning({
    title: t('Delete Record'),
    content: t('Are you sure you want to delete this record? This action cannot be undone.'),
    positiveText: t('Delete'),
    negativeText: t('Cancel'),
    onPositiveClick: async () => {
      loading.value = true
      try {
        const { deleteRecords } = await import('@/shared/api/common')
        const res = await deleteRecords(entity.value, [name])
        if (res.success) {
          message.success(res.message || t('Deleted successfully'))
          await loadData()
        } else {
          message.error(res.message || t('Delete failed'))
        }
      } catch (error) {
        message.error(t('Delete failed'))
        console.error('Delete error:', error)
      } finally {
        loading.value = false
      }
    }
  })
}


function isBooleanField(fieldName: string) {
  // 通过元数据检测布尔字段
  const fieldMeta = metaFields.value.find(f => f.fieldname === fieldName)
  if (fieldMeta) {
    // 检查字段类型
    if (fieldMeta.fieldtype === 'Check') return true
    
    // 检查是否有一个布尔值字段的特征（值为0/1）
    // 或者通过字段名包含布尔关键字检测
    const boolKeywords = ['enabled', 'disabled', 'active', 'status']
    return boolKeywords.some(keyword => fieldName.toLowerCase().includes(keyword))
  }
  return false
}

// 检查是否为Select类型字段
function isSelectField(fieldName: string) {
  const fieldMeta = metaFields.value.find(f => f.fieldname === fieldName)
  return fieldMeta?.fieldtype === 'Select'
}

// 检查是否为Icon类型字段
function isIconField(fieldName: string) {
  const fieldMeta = metaFields.value.find(f => f.fieldname === fieldName)
  return fieldMeta?.fieldtype === 'Icon'
}

// Select字段颜色配置映射（柔和、低饱和度）
// 格式：{ fieldName: { value: color } } 或 { 'global': { value: color } } 用于所有Select字段
// 推荐使用柔和颜色，如：'#e0f2fe'（浅蓝）、'#dcfce7'（浅绿）等
const selectFieldColors = ref<Record<string, Record<string, string>>>({
  // 全局默认颜色映射（适用于所有Select字段，可被字段特定配置覆盖）
  'global': {
    // 可以根据需要添加默认颜色（使用柔和色调）
  }
})

// Select字段文字颜色配置映射（与背景色配对）
// 格式与 selectFieldColors 相同，但存储的是文字颜色
const selectFieldTextColors = ref<Record<string, Record<string, string>>>({
  'global': {}
})

// 获取Select字段值的背景色
function getSelectBadgeColor(fieldName: string, value: any): string {
  if (!value || value === '') return ''
  
  const valueStr = String(value)
  
  // 1. 先检查字段特定的颜色配置
  if (selectFieldColors.value[fieldName] && selectFieldColors.value[fieldName][valueStr]) {
    return selectFieldColors.value[fieldName][valueStr]
  }
  
  // 2. 检查全局颜色配置
  if (selectFieldColors.value['global'] && selectFieldColors.value['global'][valueStr]) {
    return selectFieldColors.value['global'][valueStr]
  }
  
  // 3. 使用基于值的哈希生成默认颜色（保证同一值始终显示相同颜色）
  return getDefaultColorForValue(valueStr)
}

// 根据值生成默认颜色（使用哈希算法确保一致性）
// 使用柔和、低饱和度的现代色彩方案，适合长时间观看
function getDefaultColorForValue(value: string): string {
  // 柔和、低饱和度的现代色彩方案（背景色 + 文字色配置）
  const colors = [
  { bg: '#e6f8f0', text: '#0d684b' }, // 主品牌青绿
  { bg: '#dcfce7', text: '#166534' }, // 绿
  { bg: '#e0f2fe', text: '#0369a1' }, // 蓝
  { bg: '#fef9c3', text: '#713f12' }, // 柔黄
  { bg: '#fee2e2', text: '#991b1b' }, // 红
  { bg: '#fdf2f8', text: '#9d174d' }, // 粉
  { bg: '#f5f3ff', text: '#6d28d9' }, // 紫
  { bg: '#fff7ed', text: '#9a3412' }, // 橙
  { bg: '#f0fdfa', text: '#115e59' }, // 深青绿（呼应主色）
  { bg: '#f1f5f9', text: '#0f172a' }, // 中性灰
];
  
  // 简单的哈希函数
  let hash = 0
  for (let i = 0; i < value.length; i++) {
    hash = ((hash << 5) - hash) + value.charCodeAt(i)
    hash = hash & hash // 转换为32位整数
  }
  
  const colorConfig = colors[Math.abs(hash) % colors.length]
  // 存储文字颜色到数据中，用于动态设置
  return colorConfig.bg
}

// 获取Select字段值的文字颜色（与背景色配对）
function getSelectBadgeTextColor(fieldName: string, value: any): string {
  if (!value || value === '') return '#374151'
  
  const valueStr = String(value)
  
  // 1. 先检查字段特定的文字颜色配置
  if (selectFieldTextColors.value[fieldName] && selectFieldTextColors.value[fieldName][valueStr]) {
    return selectFieldTextColors.value[fieldName][valueStr]
  }
  
  // 2. 检查全局文字颜色配置
  if (selectFieldTextColors.value['global'] && selectFieldTextColors.value['global'][valueStr]) {
    return selectFieldTextColors.value['global'][valueStr]
  }
  
  // 3. 使用默认文字颜色（基于哈希，与背景色配对）
  const textColors = [
    '#0369a1', '#166534', '#92400e', '#991b1b', '#6b21a8',
    '#9f1239', '#0e7490', '#15803d', '#9a3412', '#4338ca'
  ]
  
  let hash = 0
  for (let i = 0; i < valueStr.length; i++) {
    hash = ((hash << 5) - hash) + valueStr.charCodeAt(i)
    hash = hash & hash
  }
  
  return textColors[Math.abs(hash) % textColors.length]
}

function formatDisplayValue(value: any, fieldName: string) {
  let result: any = value
  
  // 获取字段元数据
  const fieldMeta = metaFields.value.find(f => f.fieldname === fieldName)
  
  // 如果是Link类型字段，使用缓存的title_field值
  if (fieldMeta && fieldMeta.fieldtype === 'Link' && fieldMeta.options && value) {
    const cacheKey = `${fieldMeta.options}_${value}`
    if (linkTitleCache.value[cacheKey]) {
      result = linkTitleCache.value[cacheKey]
    } else {
      // 如果缓存中没有，返回原值（可能正在加载中）
      result = value
    }
  } else if (fieldMeta && fieldMeta.options) {
    // 尝试从字段元数据获取翻译选项（非Link字段）
    const options = fieldMeta.options.split('\n').filter((s: string) => s.trim() !== '')
    if (options.includes(value)) {
      result = t(value)
    }
  } else if (typeof value === 'string' && value.length > 0) {
    result = t(value)
  }
  
  // 简单截断：超过50字符就截断
  if (typeof result === 'string' && result.length > 50) {
    result = result.substring(0, 50) + '...'
  }
  
  return result
}
</script>

<style scoped>
.page { 
  padding: 16px; 
  width: 100%;
  min-height: 100vh;
}

.page-header {
  display: flex;
  align-items: flex-start; 
  justify-content: space-between;
  margin-bottom: 24px;
}

.header-left h2 { font-size: 28px; font-weight: 700; color: #1f2937; margin: 0; }


.agent-list { background: white; border: 1px solid #e5e7eb; border-radius: 12px; overflow: hidden; }
.list-pagination { padding: 16px 20px; border-top: 1px solid #e5e7eb; background: #f9fafb; display: flex; justify-content: center; }

/* 列表内容包装器 */
.list-content-wrapper {
  position: relative;
}

.list-content-wrapper.loading-state {
  opacity: 0.7;
  pointer-events: none;
}

/* 首次加载时显示全屏加载 */
.loading-full {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 60px 20px;
  color: #6b7280;
  font-size: 16px;
}

.loading-full i {
  margin-right: 8px;
}

/* 已有数据时的轻微加载指示（右上角浮动） */
.loading-overlay {
  position: absolute;
  top: 12px;
  right: 12px;
  z-index: 10;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  background: rgba(255, 255, 255, 0.95);
  border-radius: 50%;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
  color: #3b82f6;
  font-size: 14px;
  animation: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;
}

@keyframes pulse {
  0%, 100% {
    opacity: 1;
  }
  50% {
    opacity: 0.7;
  }
}

/* 卡片视图样式（对齐 AgentList 设计） */
.agent-grid { 
  display: grid; 
  grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); 
  gap: 20px; 
  margin-bottom: 24px; 
}

.agent-card { 
  background: white; 
  border: 1px solid #e5e7eb; 
  border-radius: 12px; 
  padding: 0;
  cursor: pointer; 
  transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1); 
  position: relative; 
  overflow: hidden;
  display: flex;
  flex-direction: column;
  height: 100%;
}

.agent-card:hover { 
  border-color: #2563eb; 
  box-shadow: 0 4px 12px rgba(37, 99, 235, 0.1); 
  transform: translateY(-2px); 
}

.agent-card.selected { 
  border-color: #3b82f6; 
  background: #f0f9ff; 
  box-shadow: 0 0 0 2px rgba(59, 130, 246, 0.1); 
}

.card-checkbox { 
  position: absolute; 
  top: 12px; 
  right: 12px; 
  z-index: 10; 
}

.card-checkbox input[type="checkbox"] { 
  cursor: pointer; 
  accent-color: #3b82f6; 
  width: 18px;
  height: 18px;
}

.card-image {
  width: 100%;
  aspect-ratio: 16 / 9;
  overflow: hidden;
  background: linear-gradient(135deg, #f3f4f6 0%, #e5e7eb 100%);
  display: flex;
  align-items: center;
  justify-content: center;
  position: relative;
}

.card-image::before {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg, rgba(0, 0, 0, 0) 0%, rgba(0, 0, 0, 0.02) 100%);
  pointer-events: none;
}

.card-image img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center;
  transition: transform 0.4s cubic-bezier(0.4, 0, 0.2, 1);
}

.agent-card:hover .card-image img {
  transform: scale(1.08);
}

.card-content { 
  display: flex; 
  flex-direction: column; 
  flex: 1;
  padding: 20px;
  padding-bottom: 12px;
  min-height: 0;
}

.info { 
  display: flex; 
  flex-direction: column; 
  gap: 10px; 
  flex: 1;
  min-width: 0;
  width: 100%;
  overflow: hidden;
}

.title { 
  font-size: 16px; 
  font-weight: 600; 
  color: #111827; 
  line-height: 1.4; 
  margin: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.desc { 
  font-size: 13px; 
  color: #6b7280; 
  line-height: 1.5; 
  margin: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.meta { 
  display: flex; 
  align-items: center; 
  gap: 6px; 
  flex-wrap: wrap; 
  margin-top: 4px;
  width: 100%;
  overflow: hidden;
}

.badge { 
  background: #f3f4f6; 
  color: #374151; 
  padding: 4px 10px; 
  border-radius: 6px; 
  font-size: 12px; 
  font-weight: 500;
  line-height: 1.4;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 100%;
  display: inline-block;
  min-width: 0;
}

/* Select字段Badge样式 - 柔和现代风格 */
.select-badge {
  display: inline-block;
  padding: 4px 12px;
  border-radius: 16px;
  font-size: 12px;
  font-weight: 500;
  white-space: nowrap;
  line-height: 1.5;
  transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
  border: 1px solid rgba(0, 0, 0, 0.06);
  backdrop-filter: blur(4px);
}

.select-badge:hover {
  transform: translateY(-1px);
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
}

/* 工具栏容器样式（保留用于布局） */
.header-right { display: flex; align-items: center; gap: 12px; }

/* 注意：操作列的样式现在由 DefaultListActions 组件和自定义操作组件自己管理 */
/* 父组件不再定义 card-actions 和 col-actions 样式，符合组件自包含的最佳实践 */

/* 列表样式 - 与 AgentList 完全一致 */
.col-checkbox {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 40px;
}

.agent-list.has-image .list-header {
  grid-template-columns: 40px minmax(50px, 50px) repeat(auto-fit, minmax(120px, 1fr)) 140px;
}

.agent-list:not(.has-image) .list-header {
  grid-template-columns: 40px repeat(auto-fit, minmax(120px, 1fr)) 140px;
}

.list-header {
  display: grid;
  align-items: center;
  gap: 16px;
  padding: 16px 20px;
  background: #f9fafb;
  border-bottom: 1px solid #e5e7eb;
  font-size: 14px;
  font-weight: 600;
  color: #374151;
}


.agent-list.has-image .list-item {
  grid-template-columns: 40px minmax(50px, 50px) repeat(auto-fit, minmax(120px, 1fr)) 140px;
}

.agent-list:not(.has-image) .list-item {
  grid-template-columns: 40px repeat(auto-fit, minmax(120px, 1fr)) 140px;
}

.list-item {
  display: grid;
  align-items: center;
  gap: 16px;
  padding: 16px 20px;
  border-bottom: 1px solid #f3f4f6;
  cursor: pointer;
  transition: background-color 0.2s cubic-bezier(0.4, 0, 0.2, 1);
}

.list-item:hover {
  background: #f9fafb;
}

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

.list-item.selected {
  background: #f0f9ff;
  border-color: #3b82f6;
}

.col-image {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 50px;
  height: 50px;
  flex-shrink: 0;
}

.col-image img {
  width: 50px;
  height: 50px;
  object-fit: cover;
  object-position: center;
  border-radius: 8px;
  border: 1px solid #e5e7eb;
  background: #f9fafb;
  transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
}

.list-item:hover .col-image img {
  border-color: #3b82f6;
  box-shadow: 0 4px 12px rgba(59, 130, 246, 0.15);
  transform: translateY(-1px);
}

.col-image .image-placeholder {
  color: #9ca3af;
  font-size: 14px;
}

/* 操作列容器样式（用于网格布局，按钮样式由 DefaultListActions 组件处理） */
.col-actions {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 4px;
}

/* 布尔值样式 */
.boolean-true {
  color: #059669;
  font-weight: bold;
  font-size: 16px;
}

.boolean-false {
  color: #9ca3af;
  font-weight: bold;
  font-size: 16px;
}

/* Icon 字段图标样式 - 灰色系 */
.icon-gray {
  color: #9ca3af;
}

/* 列表列通用样式 - 确保垂直居中 */
.list-header > div:not(.col-checkbox),
.list-item > div:not(.col-checkbox):not(.col-actions) {
  display: flex;
  align-items: center;
  min-height: 24px;
}

/* 通用截断样式 */
.col-title,
.col-subtitle,
.col-description,
.col-content {
  max-width: 200px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

</style>


