<template>
  <div class="data-table-wrapper">
    <!-- 工具栏 -->
    <div class="toolbar">
      <div class="toolbar-left">
        <span class="total-info">共 <strong>{{ total }}</strong> 条</span>
        <slot name="filter" />
      </div>
      <div class="toolbar-right">
        <div class="search-box" v-if="searchable">
          <input
            v-model="searchInput"
            type="text"
            :placeholder="searchPlaceholder || '搜索...'"
            @keyup.enter="handleSearch"
          />
          <button class="search-btn" @click="handleSearch">搜索</button>
          <button v-if="searchInput" class="clear-btn" @click="searchInput=''; handleSearch()">清除</button>
        </div>
        <slot name="actions" />
      </div>
    </div>

    <!-- 表格 -->
    <div class="table-container">
      <table>
        <thead>
          <tr>
            <slot name="header" />
          </tr>
        </thead>
        <tbody>
          <slot name="body" />
          <tr v-if="!loading && total === 0">
            <td :colspan="colCount" class="empty-cell">暂无数据</td>
          </tr>
        </tbody>
      </table>
      <div v-if="loading" class="table-loading">加载中...</div>
    </div>

    <!-- 分页 -->
    <div class="pagination" v-if="totalPages > 1">
      <button class="page-btn" :disabled="page <= 1" @click="changePage(page - 1)">上一页</button>
      <template v-for="p in visiblePages" :key="p">
        <span v-if="p === '...'" class="page-dots">...</span>
        <button v-else class="page-btn" :class="{ active: p === page }" @click="changePage(p)">{{ p }}</button>
      </template>
      <button class="page-btn" :disabled="page >= totalPages" @click="changePage(page + 1)">下一页</button>
      <span class="page-info">{{ page }} / {{ totalPages }} 页</span>
    </div>
  </div>
</template>

<script setup>
const props = defineProps({
  total: { type: Number, default: 0 },
  page: { type: Number, default: 1 },
  totalPages: { type: Number, default: 1 },
  loading: { type: Boolean, default: false },
  searchable: { type: Boolean, default: true },
  searchPlaceholder: { type: String, default: '' },
  colCount: { type: Number, default: 6 },
})

const emit = defineEmits(['search', 'page-change'])

const searchInput = ref('')

function handleSearch() {
  emit('search', searchInput.value)
}

function changePage(p) {
  if (p < 1 || p > props.totalPages) return
  emit('page-change', p)
}

const visiblePages = computed(() => {
  const pages = []
  const total = props.totalPages
  const current = props.page

  if (total <= 7) {
    for (let i = 1; i <= total; i++) pages.push(i)
  } else {
    pages.push(1)
    if (current > 3) pages.push('...')
    const start = Math.max(2, current - 1)
    const end = Math.min(total - 1, current + 1)
    for (let i = start; i <= end; i++) pages.push(i)
    if (current < total - 2) pages.push('...')
    pages.push(total)
  }
  return pages
})
</script>

<style scoped>
.data-table-wrapper {
  background: #fff;
  border-radius: 8px;
  box-shadow: 0 1px 3px rgba(0,0,0,0.06);
  overflow: hidden;
}

/* 工具栏 */
.toolbar {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 12px 20px;
  border-bottom: 1px solid #f0f0f0;
  gap: 12px;
  flex-wrap: wrap;
}

.toolbar-left {
  display: flex;
  align-items: center;
  gap: 12px;
}

.toolbar-right {
  display: flex;
  align-items: center;
  gap: 8px;
}

.total-info {
  font-size: 13px;
  color: #888;
}

.total-info strong {
  color: #333;
}

.search-box {
  display: flex;
  gap: 4px;
}

.search-box input {
  padding: 5px 10px;
  border: 1px solid #d9d9d9;
  border-radius: 4px;
  font-size: 13px;
  width: 180px;
  outline: none;
}

.search-box input:focus {
  border-color: #3a7d44;
}

.search-btn {
  padding: 5px 12px;
  background: #3a7d44;
  color: #fff;
  border: none;
  border-radius: 4px;
  font-size: 12px;
  cursor: pointer;
}

.search-btn:hover {
  background: #2d6235;
}

.clear-btn {
  padding: 5px 8px;
  background: none;
  border: 1px solid #d9d9d9;
  border-radius: 4px;
  font-size: 12px;
  cursor: pointer;
  color: #999;
}

/* 表格容器 */
.table-container {
  overflow-x: auto;
  position: relative;
  max-height: calc(100vh - 280px);
  overflow-y: auto;
}

table {
  width: 100%;
  border-collapse: collapse;
  min-width: 600px;
}

:deep(thead) {
  position: sticky;
  top: 0;
  z-index: 10;
}

:deep(thead tr) {
  background: #fafafa;
}

:deep(th) {
  padding: 10px 14px;
  text-align: left;
  font-size: 12px;
  font-weight: 600;
  color: #666;
  border-bottom: 1px solid #e8e8e8;
  white-space: nowrap;
  background: #fafafa;
}

:deep(td) {
  padding: 10px 14px;
  font-size: 13px;
  color: #333;
  border-bottom: 1px solid #f5f5f5;
  vertical-align: middle;
}

:deep(tr:hover td) {
  background: #fafbfc;
}

:deep(td strong) {
  color: #1a1a2e;
}

.empty-cell {
  text-align: center;
  color: #ccc;
  padding: 40px 14px !important;
  font-size: 14px;
}

.table-loading {
  position: absolute;
  inset: 0;
  background: rgba(255,255,255,0.8);
  display: flex;
  align-items: center;
  justify-content: center;
  color: #888;
  font-size: 14px;
}

/* 分页 */
.pagination {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 4px;
  padding: 14px 20px;
  border-top: 1px solid #f0f0f0;
}

.page-btn {
  padding: 5px 10px;
  border: 1px solid #d9d9d9;
  border-radius: 4px;
  background: #fff;
  font-size: 13px;
  cursor: pointer;
  color: #333;
  min-width: 32px;
  text-align: center;
}

.page-btn:hover:not(:disabled):not(.active) {
  border-color: #3a7d44;
  color: #3a7d44;
}

.page-btn.active {
  background: #3a7d44;
  color: #fff;
  border-color: #3a7d44;
}

.page-btn:disabled {
  opacity: 0.4;
  cursor: not-allowed;
}

.page-dots {
  padding: 0 4px;
  color: #ccc;
}

.page-info {
  margin-left: 12px;
  font-size: 12px;
  color: #aaa;
}
</style>
