From a191bd78d4eac6dda67d3bc4db9f6e93eee77c32 Mon Sep 17 00:00:00 2001 From: yuetsh <517252939@qq.com> Date: Wed, 5 Aug 2026 04:28:26 -0600 Subject: [PATCH] =?UTF-8?q?feat(admin):=20=E9=A2=98=E7=9B=AE=E5=88=97?= =?UTF-8?q?=E8=A1=A8=E6=94=AF=E6=8C=81=E6=89=B9=E9=87=8F=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?/=E7=A7=BB=E9=99=A4=E6=A0=87=E7=AD=BE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Sonnet 5 --- .../problem/components/BatchTagModal.vue | 109 ++++++++++++++++++ src/admin/problem/list.vue | 60 +++++++++- 2 files changed, 167 insertions(+), 2 deletions(-) create mode 100644 src/admin/problem/components/BatchTagModal.vue diff --git a/src/admin/problem/components/BatchTagModal.vue b/src/admin/problem/components/BatchTagModal.vue new file mode 100644 index 0000000..1e780db --- /dev/null +++ b/src/admin/problem/components/BatchTagModal.vue @@ -0,0 +1,109 @@ + + + diff --git a/src/admin/problem/list.vue b/src/admin/problem/list.vue index bfd306d..0dd98ee 100644 --- a/src/admin/problem/list.vue +++ b/src/admin/problem/list.vue @@ -11,6 +11,8 @@ import Actions from "./components/Actions.vue" import Modal from "./components/Modal.vue" import { useRouteQuery } from "@vueuse/router" import AuthorSelect from "shared/components/AuthorSelect.vue" +import type { DataTableRowKey } from "naive-ui" +import BatchTagModal from "./components/BatchTagModal.vue" interface Props { contestID?: string @@ -36,6 +38,30 @@ const { count, inc } = useCounter(0) const total = ref(0) const problems = ref([]) +const selectedRowKeys = ref([]) +const batchTagAction = ref<"add" | "remove">("add") +const [showBatchTag, toggleBatchTag] = useToggle(false) + +const selectedProblemIds = computed(() => + selectedRowKeys.value.map((key) => Number(key)), +) + +const rowKey = (row: AdminProblemFiltered) => row.id + +function chooseProblems(rowKeys: DataTableRowKey[]) { + selectedRowKeys.value = rowKeys +} + +function openBatchTag(action: "add" | "remove") { + batchTagAction.value = action + toggleBatchTag(true) +} + +function onBatchTagDone() { + selectedRowKeys.value = [] + listProblems() +} + const nextDisplayID = computed(() => { if (!isContestProblemList.value) return "" if (problems.value.length === 0) return "1" @@ -57,7 +83,7 @@ const { query, clearQuery } = usePagination({ author: useRouteQuery("author", "").value, }) -const columns: DataTableColumn[] = [ +const baseColumns: DataTableColumn[] = [ { title: "ID", key: "id", width: 100 }, { title: "显示编号", key: "_id", width: 100 }, { title: "标题", key: "title", minWidth: 200 }, @@ -141,6 +167,12 @@ const columns: DataTableColumn[] = [ }, ] +const columns = computed[]>(() => + isContestProblemList.value + ? baseColumns + : [{ type: "selection" }, ...baseColumns], +) + async function listProblems() { if (query.page < 1) query.page = 1 const offset = (query.page - 1) * query.limit @@ -212,8 +244,20 @@ watch(() => [query.page, query.limit, query.author], listProblems) > 年度趋势 + + 标签管理 + + 新建比赛题目 @@ -238,7 +282,13 @@ watch(() => [query.page, query.limit, query.author], listProblems) - + [query.page, query.limit, query.author], listProblems) :next-display-id="nextDisplayID" @change="listProblems" /> +