<!-- 管理后台审计日志页，负责只读查询和展示关键管理操作。 -->
<script setup lang="ts">
import { onMounted, reactive, ref } from "vue";
import http, { apiError } from "@/api/http";
import AppIcon from "@/components/AppIcon.vue";
import PageHeader from "@/components/PageHeader.vue";
import { useToastStore } from "@/stores/toast";

const toast = useToastStore();
const loading = ref(false);
const items = ref<Record<string, any>[]>([]);
const total = ref(0);
const query = reactive({ keyword: "", page: 1, page_size: 15 });

const actionLabels: Record<string, string> = {
  create: "新建",
  batch_create: "批量新建",
  update: "修改",
  batch_update: "批量修改",
  toggle: "状态变更",
  delete: "删除",
  batch_delete: "批量删除",
  reorder: "调整顺序",
  generate: "生成",
  save: "保存",
  save_draft: "保存草稿",
  grant_points: "增加积分",
  password_changed: "修改密码",
  password_change_failed: "修改密码失败",
};
const resourceLabels: Record<string, string> = {
  users: "用户",
  "redemption-codes": "兑换码",
  styles: "风格",
  prompts: "提示词",
  channels: "渠道",
  models: "模型",
  "admin-auth": "管理员账号",
};

/** 按当前筛选条件加载审计日志。 */
async function load() {
  loading.value = true;
  try {
    const { data } = await http.get("/audit-logs", { params: query });
    items.value = data.data.items;
    total.value = data.data.total;
  } catch (error) {
    const detail = apiError(error);
    toast.error(detail.message, detail.copyText);
  } finally {
    loading.value = false;
  }
}

/** 清空关键字并返回第一页。 */
function resetQuery() {
  query.keyword = "";
  query.page = 1;
  void load();
}

/** 将审计动作代码转换为中文业务名称。 */
function actionText(value: string) {
  return actionLabels[value] || value || "未知操作";
}

/** 将审计资源代码转换为中文业务名称。 */
function resourceText(value: string) {
  return resourceLabels[value] || value || "未知资源";
}

/** 使用中国时区格式化审计发生时间。 */
function formatTime(value: unknown) {
  if (!value) return "--";
  return new Date(String(value)).toLocaleString("zh-CN", { timeZone: "Asia/Shanghai", hour12: false });
}

onMounted(load);
</script>

<template>
  <div class="page-stack management-page">
    <PageHeader title="审计日志" />
    <section class="panel filter-bar">
      <el-input
        v-model.trim="query.keyword"
        clearable
        placeholder="管理员、操作、资源、原因、对象 ID 或追踪 ID"
        @keyup.enter="
          query.page = 1;
          load();
        "
      />
      <el-button
        type="primary"
        @click="
          query.page = 1;
          load();
        "
        >查询</el-button
      >
      <el-button @click="resetQuery">重置</el-button>
    </section>
    <section
      class="panel table-panel"
      v-loading="loading"
    >
      <el-table
        class="desktop-table"
        :data="items"
      >
        <el-table-column
          prop="admin_username"
          label="管理员"
          min-width="120"
          show-overflow-tooltip
        />
        <el-table-column
          label="操作"
          min-width="120"
        >
          <template #default="{ row }">
            <el-tag effect="plain">{{ actionText(row.action) }}</el-tag>
          </template>
        </el-table-column>
        <el-table-column
          label="资源"
          min-width="120"
        >
          <template #default="{ row }">{{ resourceText(row.resource_type) }}</template>
        </el-table-column>
        <el-table-column
          prop="resource_id"
          min-width="180"
          show-overflow-tooltip
        >
          <template #header>
            <span class="column-label">
              对象 ID
              <el-tooltip
                content="被操作数据的唯一标识；即使对象改名或删除，仍可用它准确定位记录。"
                placement="top"
              >
                <span class="column-help"><AppIcon name="QuestionFilled" /></span>
              </el-tooltip>
            </span>
          </template>
        </el-table-column>
        <el-table-column
          prop="reason"
          label="操作原因"
          min-width="180"
          show-overflow-tooltip
        >
          <template #default="{ row }">{{ row.reason || "--" }}</template>
        </el-table-column>
        <el-table-column
          prop="trace_id"
          min-width="180"
          show-overflow-tooltip
        >
          <template #header>
            <span class="column-label">
              请求追踪 ID
              <el-tooltip
                content="本次请求的唯一追踪编号，用于在服务器日志中查找并关联同一次请求。"
                placement="top"
              >
                <span class="column-help"><AppIcon name="QuestionFilled" /></span>
              </el-tooltip>
            </span>
          </template>
        </el-table-column>
        <el-table-column
          label="操作时间"
          min-width="180"
        >
          <template #default="{ row }">{{ formatTime(row.created_at) }}</template>
        </el-table-column>
      </el-table>

      <div
        v-if="items.length"
        class="mobile-card-list"
      >
        <article
          v-for="row in items"
          :key="row.id"
          class="data-card"
        >
          <dl>
            <dt>管理员</dt>
            <dd>{{ row.admin_username }}</dd>
            <dt>操作</dt>
            <dd>{{ actionText(row.action) }}</dd>
            <dt>资源</dt>
            <dd>{{ resourceText(row.resource_type) }}</dd>
            <dt>对象 ID</dt>
            <dd>{{ row.resource_id || "--" }}</dd>
            <dt>操作原因</dt>
            <dd>{{ row.reason || "--" }}</dd>
            <dt>请求追踪 ID</dt>
            <dd>{{ row.trace_id || "--" }}</dd>
            <dt>操作时间</dt>
            <dd>{{ formatTime(row.created_at) }}</dd>
          </dl>
        </article>
      </div>

      <el-empty
        v-if="!loading && !items.length"
        description="暂无审计日志"
      />
      <el-pagination
        v-if="total > query.page_size"
        v-model:current-page="query.page"
        background
        layout="total,prev,pager,next"
        :total="total"
        :page-size="query.page_size"
        @current-change="load"
      />
    </section>
  </div>
</template>

<style scoped>
.column-label,
.column-help {
  display: inline-flex;
  align-items: center;
}

.column-label {
  gap: var(--space-xs);
}

.column-help {
  color: var(--color-text-secondary);
  cursor: help;
}
</style>
