Tài liệu

Bảng điều phối kiểm duyệt

Bảng điều phối kiểm duyệt Ví dụ này tạo một trang quản trị dành cho các bình luận đang chờ duyệt. Menu Tạo một mục menu: Trường Giá trị label Moderation path /moderation permission {"or":[{"route":"/blog_comment","methods":["GET"]}]} Page Extension Tạo một page extension gắn với

Bảng điều phối kiểm duyệt

Ví dụ này tạo một trang quản trị dành cho các bình luận đang chờ duyệt.

Tạo một mục menu:

Trường Giá trị
label Moderation
path /moderation
permission {"or":[{"route":"/blog_comment","methods":["GET"]}]}

Page Extension

Tạo một page extension gắn với mục menu đó.

<template>
  <div class="space-y-4">
    <ErrorState v-if="error" :error="error" />
    <LoadingState v-else-if="pending" />
    <div v-else-if="rows.length" class="space-y-3">
      <div v-for="comment in rows" :key="comment.id" class="rounded-md border border-gray-200 p-4 dark:border-gray-800">
        <div class="flex items-start justify-between gap-3">
          <div>
            <p class="text-sm text-gray-500">{{ comment.author?.email }}</p>
            <p class="mt-2">{{ comment.body }}</p>
          </div>
          <div class="flex gap-2">
            <PermissionGate :condition="{ and: [{ route: '/blog_comment', methods: ['PATCH'] }] }">
              <UButton size="sm" color="primary" @click="updateStatus(comment.id, 'approved')">Approve</UButton>
              <UButton size="sm" color="neutral" variant="outline" @click="updateStatus(comment.id, 'rejected')">Reject</UButton>
            </PermissionGate>
          </div>
        </div>
      </div>
    </div>
    <EmptyState v-else title="No pending comments" />
  </div>
</template>

<script setup>
const { registerPageHeader } = usePageHeaderRegistry();
registerPageHeader({
  title: 'Moderation',
  description: 'Review pending comments',
  leadingIcon: '',
  variant: 'minimal'
});

const rows = ref([]);
const pending = ref(false);
const error = ref(null);

const load = async () => {
  pending.value = true;
  error.value = null;
  try {
    const response = await $fetch('/api/blog_comment', {
      query: {
        filter: JSON.stringify({ status: { _eq: 'pending' } }),
        fields: 'id,body,status,author.email,createdAt',
        sort: '-createdAt',
        limit: 25
      }
    });
    rows.value = response.data || [];
  } catch (err) {
    error.value = err;
  } finally {
    pending.value = false;
  }
};

const updateStatus = async (id, status) => {
  await $fetch(`/api/blog_comment/${id}`, {
    method: 'PATCH',
    body: { status }
  });
  await load();
};

onMounted(load);
</script>

Khi người vận hành cần xem đầy đủ metadata, dùng data route thô /data/blog_comment làm liên kết kiểm tra bổ sung.