<template>
  <div class="work-review-page">
    <a-card class="title-card">
      <template #title>作品审核</template>
    </a-card>

    <!-- 统计卡片 -->
    <div class="stats-row">
      <div v-for="item in statsItems" :key="item.key" :class="['stat-card', { active: activeFilter === item.key }]" @click="handleStatClick(item.key)">
        <div class="stat-icon" :style="{ background: item.bgColor }">
          <component :is="item.icon" :style="{ color: item.color }" />
        </div>
        <div class="stat-info">
          <span class="stat-count">{{ item.count }}</span>
          <span class="stat-label">{{ item.label }}</span>
        </div>
      </div>
    </div>

    <!-- 筛选 -->
    <div class="filter-bar">
      <a-form layout="inline" @finish="handleSearch">
        <a-form-item label="审核状态">
          <a-select v-model:value="searchStatus" style="width: 120px" @change="handleSearch">
            <a-select-option value="">全部</a-select-option>
            <a-select-option value="pending_review">待审核</a-select-option>
            <a-select-option value="published">已通过</a-select-option>
            <a-select-option value="rejected">已拒绝</a-select-option>
          </a-select>
        </a-form-item>
        <a-form-item label="作者">
          <a-input v-model:value="searchKeyword" placeholder="作者昵称" allow-clear style="width: 150px" />
        </a-form-item>
        <a-form-item>
          <a-space>
            <a-button type="primary" html-type="submit"><template #icon><SearchOutlined /></template>搜索</a-button>
            <a-button @click="handleReset"><template #icon><ReloadOutlined /></template>重置</a-button>
          </a-space>
        </a-form-item>
      </a-form>
    </div>

    <!-- 批量操作栏 -->
    <div class="batch-bar">
      <template v-if="selectedRowKeys.length > 0">
        <span>已选择 <strong>{{ selectedRowKeys.length }}</strong> 项</span>
        <a-button type="primary" size="small" :loading="batchLoading" @click="handleBatchApprove">
          <template #icon><CheckCircleOutlined /></template>
          批量通过
        </a-button>
        <a-button danger size="small" @click="openBatchReject">
          <template #icon><CloseCircleOutlined /></template>
          批量拒绝
        </a-button>
        <a-button size="small" @click="selectedRowKeys = []">取消选择</a-button>
      </template>
      <span v-else class="batch-tip">勾选表格中的待审核作品可进行批量操作</span>
    </div>

    <!-- 表格 -->
    <a-table
      :columns="columns"
      :data-source="dataSource"
      :loading="loading"
      :pagination="pagination"
      :row-selection="{ selectedRowKeys, onChange: onSelectChange, getCheckboxProps: (r: any) => ({ disabled: r.status !== 'pending_review' }) }"
      row-key="id"
      @change="handleTableChange"
      class="data-table"
    >
      <template #bodyCell="{ column, record, index }">
        <template v-if="column.key === 'index'">{{ (pagination.current - 1) * pagination.pageSize + index + 1 }}</template>
        <template v-else-if="column.key === 'cover'">
          <img v-if="record.coverUrl" :src="record.coverUrl" class="cover-thumb" />
          <div v-else class="cover-empty">无</div>
        </template>
        <template v-else-if="column.key === 'titleDesc'">
          <div class="title-cell">
            <span class="work-title">{{ record.title }}</span>
            <span v-if="record.description" class="work-desc">{{ record.description }}</span>
          </div>
        </template>
        <template v-else-if="column.key === 'author'">{{ record.creator?.nickname || '-' }}</template>
        <template v-else-if="column.key === 'tags'">
          <a-tag v-for="t in (record.tags || []).slice(0, 3)" :key="t.tag?.id" size="small">{{ t.tag?.name }}</a-tag>
          <span v-if="!record.tags?.length" style="color: #d1d5db">-</span>
        </template>
        <template v-else-if="column.key === 'status'">
          <a-tag :color="statusColor[record.status] || 'default'">{{ statusText[record.status] || record.status }}</a-tag>
        </template>
        <template v-else-if="column.key === 'createTime'">{{ formatDate(record.createTime) }}</template>
        <template v-else-if="column.key === 'reviewTime'">{{ record.reviewTime ? formatDate(record.reviewTime) : '-' }}</template>
        <template v-else-if="column.key === 'action'">
          <a-space>
            <a-button v-if="record.status === 'pending_review'" type="link" size="small" style="color: #10b981" @click="quickApprove(record.id)">通过</a-button>
            <a-button v-if="record.status === 'pending_review'" type="link" size="small" danger @click="openReject(record.id)">拒绝</a-button>
            <a-button v-if="record.status === 'published' || record.status === 'rejected'" type="link" size="small" style="color: #f59e0b" @click="handleRevoke(record.id)">撤销</a-button>
            <a-button type="link" size="small" @click="showDetail(record.id)">详情</a-button>
          </a-space>
        </template>
      </template>
    </a-table>

    <!-- 拒绝弹窗 -->
    <a-modal v-model:open="rejectVisible" :title="isBatchReject ? `批量拒绝（${selectedRowKeys.length}个作品）` : '拒绝作品'" @ok="handleReject" :confirm-loading="rejectLoading">
      <a-radio-group v-model:value="rejectReason" style="display: flex; flex-direction: column; gap: 8px">
        <a-radio value="含不适宜未成年人的内容">含不适宜未成年人的内容</a-radio>
        <a-radio value="含个人隐私信息">含个人隐私信息</a-radio>
        <a-radio value="涉嫌抄袭/侵权">涉嫌抄袭/侵权</a-radio>
        <a-radio value="内容质量不符合发布标准">内容质量不符合发布标准</a-radio>
        <a-radio value="other">其他</a-radio>
      </a-radio-group>
      <a-input v-if="rejectReason === 'other'" v-model:value="rejectCustom" placeholder="请输入拒绝原因" style="margin-top: 12px" />
    </a-modal>

    <!-- 详情 Drawer -->
    <a-drawer v-model:open="detailVisible" title="作品审核详情" :width="580" :destroy-on-close="true">
      <template v-if="detailData">
        <!-- 顶部快速导航 -->
        <div class="detail-nav">
          <a-button :disabled="!hasPrevPending" size="small" @click="gotoPrevPending">
            <left-outlined /> 上一个
          </a-button>
          <span class="detail-nav-info">
            {{ detailData.title }}
            <a-tag :color="statusColor[detailData.status]" style="margin-left: 8px">{{ statusText[detailData.status] }}</a-tag>
          </span>
          <a-button :disabled="!hasNextPending" size="small" @click="gotoNextPending">
            下一个 <right-outlined />
          </a-button>
        </div>

        <a-descriptions :column="2" bordered size="small" style="margin-top: 16px">
          <a-descriptions-item label="作者">{{ detailData.creator?.nickname }}</a-descriptions-item>
          <a-descriptions-item label="用户类型">{{ detailData.creator?.userType === 'child' ? '子女' : '成人' }}</a-descriptions-item>
          <a-descriptions-item label="页数">{{ detailData._count?.pages || 0 }}</a-descriptions-item>
          <a-descriptions-item label="提交时间">{{ formatDate(detailData.createTime) }}</a-descriptions-item>
          <a-descriptions-item v-if="detailData.reviewTime" label="审核时间" :span="2">{{ formatDate(detailData.reviewTime) }}</a-descriptions-item>
        </a-descriptions>

        <!-- 作品描述 -->
        <div v-if="detailData.description" class="detail-section">
          <h4>作品简介</h4>
          <p class="detail-desc">{{ detailData.description }}</p>
        </div>

        <!-- 标签 -->
        <div v-if="detailData.tags?.length" class="detail-section">
          <h4>标签</h4>
          <div style="display: flex; gap: 6px; flex-wrap: wrap">
            <a-tag v-for="t in detailData.tags" :key="t.tag?.id" color="purple">{{ t.tag?.name }}</a-tag>
          </div>
        </div>

        <!-- 绘本翻页预览 -->
        <div v-if="detailData.pages?.length" class="preview-section">
          <h4>绘本内容预览</h4>
          <div class="page-preview">
            <img v-if="detailData.pages[previewPage]?.imageUrl" :src="detailData.pages[previewPage].imageUrl" class="preview-img" />
            <p v-if="detailData.pages[previewPage]?.text" class="preview-text">{{ detailData.pages[previewPage].text }}</p>
            <div class="preview-nav">
              <a-button :disabled="previewPage === 0" size="small" @click="previewPage--">上一页</a-button>
              <span>{{ previewPage + 1 }} / {{ detailData.pages.length }}</span>
              <a-button :disabled="previewPage === detailData.pages.length - 1" size="small" @click="previewPage++">下一页</a-button>
            </div>
          </div>
        </div>

        <!-- 审核操作 -->
        <div v-if="detailData.status === 'pending_review'" class="review-actions">
          <a-space style="width: 100%">
            <a-button type="primary" style="flex: 1" @click="approveInDrawer">通过</a-button>
            <a-button danger style="flex: 1" @click="rejectInDrawer">拒绝</a-button>
          </a-space>
        </div>
        <div v-else-if="detailData.status === 'published' || detailData.status === 'rejected'" class="review-actions">
          <a-button block style="color: #f59e0b; border-color: #f59e0b" @click="handleRevoke(detailData.id)">撤销审核</a-button>
        </div>

        <!-- 操作日志 -->
        <div class="log-section">
          <h4>操作日志</h4>
          <div v-if="detailLogs.length === 0" class="log-empty">暂无操作记录</div>
          <a-timeline v-else>
            <a-timeline-item
              v-for="log in detailLogs"
              :key="log.id"
              :color="logActionColor[log.action] || 'gray'"
            >
              <div class="log-item">
                <span class="log-action">{{ logActionText[log.action] || log.action }}</span>
                <span class="log-operator">{{ log.operator?.nickname || '系统' }}</span>
                <span class="log-time">{{ formatDate(log.createTime) }}</span>
              </div>
              <div v-if="log.reason" class="log-reason">原因：{{ log.reason }}</div>
              <div v-if="log.note" class="log-note">备注：{{ log.note }}</div>
            </a-timeline-item>
          </a-timeline>
        </div>
      </template>
    </a-drawer>
  </div>
</template>

<script setup lang="ts">
import { ref, reactive, computed, onMounted } from 'vue'
import { message, Modal } from 'ant-design-vue'
import {
  SearchOutlined, ReloadOutlined, ClockCircleOutlined, CheckCircleOutlined,
  CloseCircleOutlined, FileTextOutlined, LeftOutlined, RightOutlined,
} from '@ant-design/icons-vue'
import request from '@/utils/request'
import dayjs from 'dayjs'

const loading = ref(false)
const dataSource = ref<any[]>([])
const pagination = reactive({ current: 1, pageSize: 10, total: 0, showSizeChanger: true, showTotal: (t: number) => `共 ${t} 条` })
// #1 默认筛选待审核
const searchStatus = ref('pending_review')
const searchKeyword = ref('')
const activeFilter = ref('pending_review')

// 批量选择
const selectedRowKeys = ref<number[]>([])
const batchLoading = ref(false)
const onSelectChange = (keys: number[]) => { selectedRowKeys.value = keys }

const stats = ref({ pending: 0, todayReviewed: 0, todayApproved: 0, todayRejected: 0 })
const statsItems = computed(() => [
  { key: 'pending_review', label: '待审核', count: stats.value.pending, icon: ClockCircleOutlined, color: '#f59e0b', bgColor: 'rgba(245,158,11,0.1)' },
  { key: 'today', label: '今日已审', count: stats.value.todayReviewed, icon: FileTextOutlined, color: '#6366f1', bgColor: 'rgba(99,102,241,0.1)' },
  { key: 'approved', label: '今日通过', count: stats.value.todayApproved, icon: CheckCircleOutlined, color: '#10b981', bgColor: 'rgba(16,185,129,0.1)' },
  { key: 'rejected', label: '今日拒绝', count: stats.value.todayRejected, icon: CloseCircleOutlined, color: '#ef4444', bgColor: 'rgba(239,68,68,0.1)' },
])

const statusColor: Record<string, string> = { pending_review: 'orange', published: 'green', rejected: 'red', taken_down: 'default' }
const statusText: Record<string, string> = { pending_review: '待审核', published: '已通过', rejected: '已拒绝', taken_down: '已下架', draft: '草稿' }
const logActionText: Record<string, string> = { approve: '审核通过', reject: '审核拒绝', takedown: '下架', restore: '恢复', revoke: '撤销审核' }
const logActionColor: Record<string, string> = { approve: 'green', reject: 'red', takedown: 'gray', restore: 'blue', revoke: 'orange' }
const formatDate = (d: string) => d ? dayjs(d).format('YYYY-MM-DD HH:mm') : '-'

// #2 合并标题+描述列  #4 增加审核时间列
const columns = [
  { title: '序号', key: 'index', width: 50 },
  { title: '封面', key: 'cover', width: 70 },
  { title: '作品名称', key: 'titleDesc', width: 220 },
  { title: '页数', dataIndex: ['_count', 'pages'], key: 'pages', width: 50 },
  { title: '作者', key: 'author', width: 90 },
  { title: '标签', key: 'tags', width: 130 },
  { title: '状态', key: 'status', width: 80 },
  { title: '提交时间', key: 'createTime', width: 130 },
  { title: '审核时间', key: 'reviewTime', width: 130 },
  { title: '操作', key: 'action', width: 190, fixed: 'right' as const },
]

// 拒绝
const rejectVisible = ref(false)
const rejectLoading = ref(false)
const rejectTargetId = ref<number | null>(null)
const rejectReason = ref('')
const rejectCustom = ref('')

// 详情 + 日志
const detailVisible = ref(false)
const detailData = ref<any>(null)
const detailLogs = ref<any[]>([])
const previewPage = ref(0)
const currentDetailIndex = ref(-1)

// #3 详情内「上一个/下一个」导航
const pendingItems = computed(() => dataSource.value.filter(d => d.status === 'pending_review'))
const hasPrevPending = computed(() => {
  if (currentDetailIndex.value < 0) return false
  // 在当前列表中找前一个待审核
  const currentId = detailData.value?.id
  const idx = dataSource.value.findIndex(d => d.id === currentId)
  for (let i = idx - 1; i >= 0; i--) {
    if (dataSource.value[i].status === 'pending_review') return true
  }
  return false
})
const hasNextPending = computed(() => {
  const currentId = detailData.value?.id
  const idx = dataSource.value.findIndex(d => d.id === currentId)
  for (let i = idx + 1; i < dataSource.value.length; i++) {
    if (dataSource.value[i].status === 'pending_review') return true
  }
  return false
})

const gotoPrevPending = () => {
  const currentId = detailData.value?.id
  const idx = dataSource.value.findIndex(d => d.id === currentId)
  for (let i = idx - 1; i >= 0; i--) {
    if (dataSource.value[i].status === 'pending_review') {
      showDetail(dataSource.value[i].id)
      return
    }
  }
}

const gotoNextPending = () => {
  const currentId = detailData.value?.id
  const idx = dataSource.value.findIndex(d => d.id === currentId)
  for (let i = idx + 1; i < dataSource.value.length; i++) {
    if (dataSource.value[i].status === 'pending_review') {
      showDetail(dataSource.value[i].id)
      return
    }
  }
}

// 详情内审核操作后自动跳下一个
const approveInDrawer = async () => {
  const id = detailData.value?.id
  if (!id) return
  try {
    await request.post(`/content-review/works/${id}/approve`, {})
    message.success('已通过')
    fetchList(); fetchStats()
    // 自动跳下一个待审核
    const idx = dataSource.value.findIndex(d => d.id === id)
    let nextId: number | null = null
    for (let i = idx + 1; i < dataSource.value.length; i++) {
      if (dataSource.value[i].status === 'pending_review') { nextId = dataSource.value[i].id; break }
    }
    if (!nextId) {
      for (let i = idx - 1; i >= 0; i--) {
        if (dataSource.value[i].status === 'pending_review') { nextId = dataSource.value[i].id; break }
      }
    }
    if (nextId) {
      showDetail(nextId)
    } else {
      detailVisible.value = false
    }
  } catch { message.error('操作失败') }
}

const rejectInDrawer = () => {
  openReject(detailData.value?.id)
}

const fetchStats = async () => {
  try { stats.value = await request.get('/content-review/works/stats') as any } catch { /* */ }
}

const fetchList = async () => {
  loading.value = true
  try {
    const res: any = await request.get('/content-review/works', {
      params: { page: pagination.current, pageSize: pagination.pageSize, status: searchStatus.value || undefined, keyword: searchKeyword.value || undefined },
    })
    dataSource.value = res.list
    pagination.total = res.total
  } catch { message.error('获取失败') }
  finally { loading.value = false }
}

// #6 今日已审点击 → 展示今日审核过的（通过+拒绝）
const handleStatClick = (key: string) => {
  if (activeFilter.value === key) {
    activeFilter.value = ''
    searchStatus.value = ''
  } else {
    activeFilter.value = key
    if (key === 'pending_review') searchStatus.value = 'pending_review'
    else if (key === 'approved') searchStatus.value = 'published'
    else if (key === 'rejected') searchStatus.value = 'rejected'
    else searchStatus.value = ''
  }
  pagination.current = 1
  fetchList()
}

const handleSearch = () => { activeFilter.value = ''; pagination.current = 1; fetchList() }
const handleReset = () => {
  // #1 重置回默认待审核
  searchStatus.value = 'pending_review'; searchKeyword.value = ''; activeFilter.value = 'pending_review'
  selectedRowKeys.value = []; pagination.current = 1; fetchList(); fetchStats()
}
const handleTableChange = (pag: any) => { pagination.current = pag.current; pagination.pageSize = pag.pageSize; fetchList() }

const quickApprove = async (id: number) => {
  try { await request.post(`/content-review/works/${id}/approve`, {}); message.success('已通过'); fetchList(); fetchStats() }
  catch { message.error('操作失败') }
}

const handleBatchApprove = async () => {
  if (selectedRowKeys.value.length === 0) return
  batchLoading.value = true
  try {
    const res: any = await request.post('/content-review/works/batch-approve', { ids: selectedRowKeys.value })
    message.success(`已批量通过 ${res.count} 个作品`)
    selectedRowKeys.value = []
    fetchList(); fetchStats()
  } catch { message.error('批量操作失败') }
  finally { batchLoading.value = false }
}

const handleRevoke = (id: number) => {
  Modal.confirm({
    title: '确定撤销审核？',
    content: '撤销后作品将恢复为待审核状态',
    okText: '确定撤销',
    onOk: async () => {
      try {
        await request.post(`/content-review/works/${id}/revoke`)
        message.success('已撤销')
        fetchList(); fetchStats()
        // 如果在详情里撤销，刷新详情
        if (detailVisible.value && detailData.value?.id === id) {
          showDetail(id)
        }
      } catch { message.error('撤销失败') }
    },
  })
}

const isBatchReject = ref(false)
const openReject = (id: number) => { rejectTargetId.value = id; isBatchReject.value = false; rejectReason.value = ''; rejectCustom.value = ''; rejectVisible.value = true }
const openBatchReject = () => { rejectTargetId.value = null; isBatchReject.value = true; rejectReason.value = ''; rejectCustom.value = ''; rejectVisible.value = true }
const handleReject = async () => {
  const reason = rejectReason.value === 'other' ? rejectCustom.value : rejectReason.value
  if (!reason) { message.warning('请选择拒绝原因'); return }
  rejectLoading.value = true
  try {
    if (isBatchReject.value) {
      const res: any = await request.post('/content-review/works/batch-reject', { ids: selectedRowKeys.value, reason })
      message.success(`已批量拒绝 ${res.count} 个作品`)
      selectedRowKeys.value = []
    } else {
      await request.post(`/content-review/works/${rejectTargetId.value}/reject`, { reason })
      message.success('已拒绝')
    }
    rejectVisible.value = false; fetchList(); fetchStats()
    // 如果在详情 Drawer 中拒绝，自动跳下一个
    if (detailVisible.value && !isBatchReject.value) {
      const idx = dataSource.value.findIndex(d => d.id === rejectTargetId.value)
      let nextId: number | null = null
      for (let i = idx + 1; i < dataSource.value.length; i++) {
        if (dataSource.value[i].status === 'pending_review') { nextId = dataSource.value[i].id; break }
      }
      if (nextId) { showDetail(nextId) } else { detailVisible.value = false }
    }
  } catch { message.error('操作失败') }
  finally { rejectLoading.value = false }
}

const showDetail = async (id: number) => {
  previewPage.value = 0
  detailLogs.value = []
  try {
    const [work, logs]: any[] = await Promise.all([
      request.get(`/content-review/works/${id}`),
      request.get('/content-review/logs', { params: { workId: id, pageSize: 50 } }),
    ])
    detailData.value = work
    detailLogs.value = logs.list || []
    detailVisible.value = true
  } catch { message.error('获取详情失败') }
}

onMounted(() => { fetchStats(); fetchList() })
</script>

<style scoped lang="scss">
$primary: #6366f1;
.title-card { margin-bottom: 16px; border: none; border-radius: 12px; box-shadow: 0 2px 12px rgba(0,0,0,0.06); :deep(.ant-card-head) { border-bottom: none; .ant-card-head-title { font-size: 18px; font-weight: 600; } } :deep(.ant-card-body) { padding: 0; } }
.stats-row { display: flex; gap: 12px; margin-bottom: 16px; }
.stat-card { flex: 1; display: flex; align-items: center; gap: 12px; padding: 14px 16px; background: #fff; border-radius: 12px; box-shadow: 0 2px 12px rgba(0,0,0,0.06); cursor: pointer; border: 2px solid transparent; transition: all 0.2s;
  &:hover { box-shadow: 0 4px 16px rgba($primary, 0.12); } &.active { border-color: $primary; background: rgba($primary, 0.02); }
  .stat-icon { width: 36px; height: 36px; border-radius: 8px; display: flex; align-items: center; justify-content: center; font-size: 16px; flex-shrink: 0; }
  .stat-info { display: flex; flex-direction: column; .stat-count { font-size: 18px; font-weight: 700; color: #1e1b4b; line-height: 1.2; } .stat-label { font-size: 12px; color: #9ca3af; } }
}
.filter-bar { padding: 20px 24px; background: #fff; border-radius: 12px; box-shadow: 0 2px 12px rgba(0,0,0,0.06); margin-bottom: 16px; }

.batch-bar {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 10px 20px;
  background: rgba($primary, 0.03);
  border: 1px dashed rgba($primary, 0.15);
  border-radius: 10px;
  margin-bottom: 16px;
  min-height: 42px;

  span { font-size: 13px; color: #374151; strong { color: $primary; } }
  .batch-tip { font-size: 12px; color: #9ca3af; }
}

.data-table { :deep(.ant-table-wrapper) { background: #fff; border-radius: 12px; box-shadow: 0 2px 12px rgba(0,0,0,0.06); overflow: hidden; .ant-table-thead > tr > th { background: #fafafa; font-weight: 600; } .ant-table-tbody > tr:hover > td { background: rgba($primary, 0.03); } .ant-table-pagination { padding: 16px; margin: 0; } } }

// #2 标题+描述合并列
.title-cell {
  display: flex; flex-direction: column; gap: 2px;
  .work-title { font-size: 13px; font-weight: 600; color: #1e1b4b; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .work-desc { font-size: 11px; color: #9ca3af; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 200px; }
}

.cover-thumb { width: 48px; height: 64px; object-fit: cover; border-radius: 6px; }
.cover-empty { width: 48px; height: 64px; background: #f3f4f6; border-radius: 6px; display: flex; align-items: center; justify-content: center; font-size: 10px; color: #d1d5db; }

// #3 详情顶部导航
.detail-nav {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 12px 16px;
  background: #fafafa;
  border-radius: 10px;

  .detail-nav-info {
    flex: 1; text-align: center;
    font-size: 14px; font-weight: 600; color: #1e1b4b;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  }
}

// #5 详情描述和标签区
.detail-section {
  margin-top: 16px;
  h4 { font-size: 13px; font-weight: 600; color: #374151; margin: 0 0 8px; }
  .detail-desc { font-size: 13px; color: #6b7280; line-height: 1.6; margin: 0; }
}

.preview-section { margin-top: 20px; h4 { font-size: 14px; font-weight: 600; color: #1e1b4b; margin: 0 0 12px; padding-bottom: 8px; border-bottom: 1px solid #f0ecf9; } }
.page-preview {
  .preview-img { width: 100%; max-height: 300px; object-fit: contain; border-radius: 8px; margin-bottom: 8px; }
  .preview-text { font-size: 13px; color: #374151; line-height: 1.6; padding: 8px 0; }
  .preview-nav { display: flex; align-items: center; justify-content: space-between; padding: 8px 0; span { font-size: 12px; color: #6b7280; } }
}
.review-actions { margin-top: 20px; padding-top: 16px; border-top: 1px solid #f0ecf9;
  :deep(.ant-space) { display: flex; .ant-space-item { flex: 1; .ant-btn { width: 100%; } } }
}

// 操作日志
.log-section {
  margin-top: 24px;
  h4 { font-size: 14px; font-weight: 600; color: #1e1b4b; margin: 0 0 16px; padding-bottom: 8px; border-bottom: 1px solid #f0ecf9; }
  .log-empty { font-size: 13px; color: #9ca3af; text-align: center; padding: 20px 0; }
}
.log-item {
  display: flex; align-items: center; gap: 8px;
  .log-action { font-size: 13px; font-weight: 600; color: #1e1b4b; }
  .log-operator { font-size: 12px; color: #6b7280; }
  .log-time { font-size: 11px; color: #9ca3af; margin-left: auto; }
}
.log-reason, .log-note { font-size: 12px; color: #6b7280; margin-top: 2px; }
</style>
