Files
OCS_service/app/components/dashboard/QaRecordsTable.vue
T

183 lines
4.5 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!-- app/components/dashboard/QaRecordsTable.vue - 最近问答记录表格基于已准备好的 TableCom -->
<script lang="ts" setup>
import { Eye } from "lucide-vue-next";
import { storeToRefs } from "pinia";
import TableCom from "@/components/Table/TableCom.vue";
import type { TableColumn } from "@/components/Table/type";
import { Badge } from "@/components/ui/badge";
import { Button } from "@/components/ui/button";
import {
Card,
CardContent,
CardDescription,
CardHeader,
CardTitle
} from "@/components/ui/card";
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue
} from "@/components/ui/select";
import type { IQaRecord } from "@/interfaces";
import {
DASHBOARD_PAGE_SIZE_OPTIONS,
QUESTION_TYPE_LABELS,
useAnswerStore
} from "@/stores/answer";
const answerStore = useAnswerStore();
const {
pagedRecords,
recordCount,
recordsLoading,
recordsPage,
recordsPageSize
} = storeToRefs(answerStore);
/** TableCom 列配置集中在组件顶部,便于和其他项目的表格风格保持一致 */
const columns = computed<TableColumn[]>(() => [
{
label: "时间",
slot: "time",
width: 170
},
{
label: "题型",
slot: "type",
width: 100,
cellAlign: "center",
headerAlign: "center"
},
{
label: "题目",
slot: "question",
minWidth: 280
},
{
label: "选项",
slot: "options",
minWidth: 220
},
{
label: "答案",
slot: "answer",
minWidth: 160
},
{
label: "操作",
slot: "action",
width: 90,
cellAlign: "center",
headerAlign: "center"
}
]);
/** 题型英文值兜底展示原值,避免未来 OCS 扩展题型时表格为空 */
const getQuestionTypeLabel = (type: string) => {
return QUESTION_TYPE_LABELS[type] || type || "自动判断";
};
/** 空选项统一展示占位,不在表格中撑开大段空白 */
const displayOptions = (record: IQaRecord) => {
return record.options || "-";
};
</script>
<template>
<Card>
<CardHeader>
<div class="flex items-center justify-between gap-4">
<div>
<CardTitle>最近问答记录</CardTitle>
<CardDescription>分页展示按创建时间倒序</CardDescription>
</div>
<Select
:model-value="String(recordsPageSize)"
@update:model-value="(v) => answerStore.setRecordsPageSize(Number(v))"
>
<SelectTrigger class="w-28">
<SelectValue />
</SelectTrigger>
<SelectContent>
<SelectItem
v-for="size in DASHBOARD_PAGE_SIZE_OPTIONS"
:key="size"
:value="String(size)"
>
{{ size }} 条/页
</SelectItem>
</SelectContent>
</Select>
</div>
</CardHeader>
<CardContent>
<TableCom
:data="pagedRecords"
:columns="columns"
:load="recordsLoading"
:buffer="true"
:pagination="{
currentPage: recordsPage,
total: recordCount,
pageSize: recordsPageSize,
align: 'end'
}"
cell-align="left"
header-align="start"
cell-class-name="align-top"
@page:change="answerStore.setRecordsPage"
>
<template #time="{ value }">
<span class="whitespace-nowrap text-foreground">{{ value }}</span>
</template>
<template #type="{ value }">
<Badge variant="secondary" class="text-center">
{{ getQuestionTypeLabel(value) }}
</Badge>
</template>
<template #question="{ value }">
<div class="max-w-136 truncate text-foreground" :title="value">
{{ value }}
</div>
</template>
<template #options="{ row }">
<div
class="max-w-md truncate text-muted-foreground"
:title="displayOptions(row)"
>
{{ displayOptions(row) }}
</div>
</template>
<template #answer="{ value }">
<div
class="max-w-[20rem] truncate font-medium text-foreground"
:title="value"
>
{{ value }}
</div>
</template>
<template #action="{ row }">
<Button
type="button"
variant="outline"
size="icon-sm"
title="查看详情"
@click.stop="answerStore.selectRecord(row)"
>
<Eye class="size-4" />
</Button>
</template>
</TableCom>
</CardContent>
</Card>
</template>