perf: paginate admin audit lists
This commit is contained in:
@@ -0,0 +1,22 @@
|
||||
<script setup lang="ts">
|
||||
defineProps<{ page: number; pageSize: number; total: number }>();
|
||||
const emit = defineEmits<{ change: [page: number, pageSize: number] }>();
|
||||
|
||||
function changePage(page: number, pageSize: number) { emit("change", page, pageSize); }
|
||||
function changeSize(pageSize: number) { emit("change", 1, pageSize); }
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="admin-pagination">
|
||||
<el-pagination
|
||||
background
|
||||
:current-page="page"
|
||||
:page-size="pageSize"
|
||||
:page-sizes="[10, 20, 50, 100]"
|
||||
:total="total"
|
||||
layout="total, sizes, prev, pager, next, jumper"
|
||||
@current-change="changePage($event, pageSize)"
|
||||
@size-change="changeSize"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
@@ -1,9 +1,10 @@
|
||||
<script setup lang="ts">
|
||||
import { ElMessage, ElMessageBox } from "element-plus";
|
||||
import { computed, onMounted, reactive, ref } from "vue";
|
||||
import { onMounted, reactive, ref } from "vue";
|
||||
|
||||
import { api } from "../services/api";
|
||||
import TableRowActions from "./TableRowActions.vue";
|
||||
import AdminPagination from "./AdminPagination.vue";
|
||||
import type {
|
||||
KnowledgeDetail,
|
||||
KnowledgeItem,
|
||||
@@ -34,6 +35,7 @@ const resolvingNode = ref(false);
|
||||
const nodeResolved = ref(false);
|
||||
const sourceTitle = ref("");
|
||||
const filter = reactive({ keyword: "", type: "", open: "", source: "", pending: "" });
|
||||
const pager = reactive({ page: 1, pageSize: 20, total: 0 });
|
||||
const form = reactive({
|
||||
name: "",
|
||||
feishuSpaceId: "",
|
||||
@@ -46,22 +48,19 @@ const form = reactive({
|
||||
const editForm = reactive({ id: 0, name: "", knowledgeType: "general", reviewMode: "manual" });
|
||||
const batchForm = reactive({ knowledgeType: "", reviewMode: "" });
|
||||
|
||||
const filteredRows = computed(() => rows.value.filter((item) => {
|
||||
if (filter.keyword && !`${item.name}${item.sourceTitle || ""}`.includes(filter.keyword)) return false;
|
||||
if (filter.type && item.knowledgeType !== filter.type) return false;
|
||||
if (filter.open && String(item.status) !== filter.open) return false;
|
||||
if (filter.source && item.sourceStatus !== filter.source) return false;
|
||||
if (filter.pending === "yes" && !item.pendingVersionId) return false;
|
||||
if (filter.pending === "no" && item.pendingVersionId) return false;
|
||||
return true;
|
||||
}));
|
||||
|
||||
onMounted(load);
|
||||
|
||||
async function load() {
|
||||
async function load(page = pager.page, pageSize = pager.pageSize) {
|
||||
loading.value = true;
|
||||
try {
|
||||
[rows.value, migration.value] = await Promise.all([api.knowledge(), api.migrationSummary()]);
|
||||
const result = await api.knowledge({
|
||||
keyword: filter.keyword, knowledgeType: filter.type, openStatus: filter.open,
|
||||
sourceStatus: filter.source, pending: filter.pending === "" ? undefined : filter.pending === "yes",
|
||||
page, pageSize,
|
||||
});
|
||||
rows.value = result.items;
|
||||
Object.assign(pager, { page: result.page, pageSize: result.pageSize, total: result.total });
|
||||
if (!migration.value) migration.value = await api.migrationSummary();
|
||||
} catch (error) {
|
||||
ElMessage.error(errorMessage(error, "知识库列表加载失败"));
|
||||
} finally {
|
||||
@@ -429,11 +428,11 @@ async function confirmAction(
|
||||
</section>
|
||||
|
||||
<div class="knowledge-filters">
|
||||
<el-input v-model="filter.keyword" placeholder="搜索后台名称或飞书标题" clearable />
|
||||
<el-select v-model="filter.type" placeholder="知识库类型" clearable><el-option label="课程" value="course" /><el-option label="答疑" value="qa" /><el-option label="通用" value="general" /></el-select>
|
||||
<el-select v-model="filter.open" placeholder="开放状态" clearable><el-option label="已开放" value="1" /><el-option label="已关闭" value="0" /></el-select>
|
||||
<el-select v-model="filter.source" placeholder="源状态" clearable><el-option label="正常" value="normal" /><el-option label="源异常" value="error" /></el-select>
|
||||
<el-select v-model="filter.pending" placeholder="待发布版本" clearable><el-option label="有待发布版本" value="yes" /><el-option label="无待发布版本" value="no" /></el-select>
|
||||
<el-input v-model="filter.keyword" placeholder="搜索后台名称或飞书标题" clearable @change="load(1)" />
|
||||
<el-select v-model="filter.type" placeholder="知识库类型" clearable @change="load(1)"><el-option label="课程" value="course" /><el-option label="答疑" value="qa" /><el-option label="通用" value="general" /></el-select>
|
||||
<el-select v-model="filter.open" placeholder="开放状态" clearable @change="load(1)"><el-option label="已开放" value="1" /><el-option label="已关闭" value="0" /></el-select>
|
||||
<el-select v-model="filter.source" placeholder="源状态" clearable @change="load(1)"><el-option label="正常" value="normal" /><el-option label="源异常" value="error" /></el-select>
|
||||
<el-select v-model="filter.pending" placeholder="待发布版本" clearable @change="load(1)"><el-option label="有待发布版本" value="yes" /><el-option label="无待发布版本" value="no" /></el-select>
|
||||
</div>
|
||||
|
||||
<div class="knowledge-batch-bar">
|
||||
@@ -441,7 +440,7 @@ async function confirmAction(
|
||||
<el-button :disabled="selectedRows.length === 0" @click="openBatchEdit">批量修改类型/审核方式</el-button>
|
||||
</div>
|
||||
|
||||
<el-table v-loading="loading" :data="filteredRows" stripe @selection-change="selectedRows = $event">
|
||||
<el-table v-loading="loading" :data="rows" stripe @selection-change="selectedRows = $event">
|
||||
<el-table-column type="selection" width="48" />
|
||||
<el-table-column label="知识库" min-width="240"><template #default="{ row }"><strong>{{ row.name }}</strong><small class="table-subline">{{ row.sourceTitle || "尚未同步源标题" }}</small></template></el-table-column>
|
||||
<el-table-column label="类型/审核" width="150"><template #default="{ row }">{{ typeLabel(row.knowledgeType) }}<small class="table-subline">{{ row.reviewMode === 'manual' ? '人工审核' : '允许自动发布' }}</small></template></el-table-column>
|
||||
@@ -450,6 +449,7 @@ async function confirmAction(
|
||||
<el-table-column prop="lastSyncedAt" label="最近同步" width="180" />
|
||||
<el-table-column label="操作" width="220" fixed="right"><template #default="{ row }"><TableRowActions><el-button link type="primary" @click="openDetail(row)">详情</el-button><el-button link type="primary" :disabled="row.lifecycleStatus === 'archived'" :loading="operatingId === row.id" @click="sync(row, 'review')">同步</el-button><el-dropdown trigger="click" :teleported="true" @command="handleMore($event, row)"><el-button link type="primary">更多</el-button><template #dropdown><el-dropdown-menu><el-dropdown-item command="detail">查看详情</el-dropdown-item><el-dropdown-item command="preview">进入 Agent 预览</el-dropdown-item><el-dropdown-item command="versions">查看版本</el-dropdown-item><el-dropdown-item v-if="row.lifecycleStatus === 'active'" command="archive" divided>归档</el-dropdown-item><el-dropdown-item v-else command="restore" divided>恢复</el-dropdown-item><el-dropdown-item command="delete" :disabled="row.lifecycleStatus !== 'archived'" divided>删除</el-dropdown-item></el-dropdown-menu></template></el-dropdown></TableRowActions></template></el-table-column>
|
||||
</el-table>
|
||||
<AdminPagination :page="pager.page" :page-size="pager.pageSize" :total="pager.total" @change="load" />
|
||||
|
||||
<el-drawer v-model="detailOpen" size="76%" title="知识库详情" destroy-on-close>
|
||||
<template v-if="detail">
|
||||
|
||||
Reference in New Issue
Block a user