- 迁移 0022:problem_tag 加 category(knowledge / theme)和 category_confirmed; 存量 25 个题材、题集类标签归主题,其余归知识点,全部记为已确认 - 前台题目列表按两组显示标签,组内按题目数从多到少 - 后台标签管理:每行切换分类;出题时新建的标签默认知识点、标「待归类」并排在最前, 页头提示待归类数量,可点「确认」保留默认;加分类筛选 - 新接口 PUT /admin/problem-tags/:id/category,设置分类即视为确认 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
e1b6a9e9fa
commit
d07459928d
12 files changed
+4226
-30
No files matched your search
@@ -104,6 +104,22 @@ async function listTags() {
|
||||
}))
|
||||
}
|
||||
|
||||
// 知识点在前、主题在后;组内按题目数从多到少,最常用的「输入输出」「选择结构」
|
||||
// 排在最前面,不再和一堆游戏名按拼音混排
|
||||
const TAG_GROUPS = [
|
||||
{ category: "knowledge", label: "知识点" },
|
||||
{ category: "theme", label: "主题" },
|
||||
] as const
|
||||
|
||||
const tagGroups = computed(() =>
|
||||
TAG_GROUPS.map((group) => ({
|
||||
...group,
|
||||
tags: tags.value
|
||||
.filter((t) => t.category === group.category)
|
||||
.sort((a, b) => b.problemCount - a.problemCount),
|
||||
})).filter((group) => group.tags.length > 0),
|
||||
)
|
||||
|
||||
function chooseTag(tag: Tag) {
|
||||
query.tag = tag.checked ? "" : tag.name
|
||||
tags.value = tags.value.map((t) => {
|
||||
@@ -293,18 +309,24 @@ function rowProps(row: ProblemRow) {
|
||||
<Hitokoto v-if="isDesktop" class="problem-list-hitokoto" />
|
||||
</div>
|
||||
<n-collapse-transition :show="showTag">
|
||||
<n-flex>
|
||||
<n-tag
|
||||
v-for="tag in tags"
|
||||
:closable="tag.checked"
|
||||
@close="chooseTag(tag)"
|
||||
@click="chooseTag(tag)"
|
||||
:key="tag.id"
|
||||
:type="tag.checked ? 'success' : 'default'"
|
||||
>
|
||||
{{ tag.name }}
|
||||
</n-tag>
|
||||
</n-flex>
|
||||
<div class="tag-groups">
|
||||
<div v-for="group in tagGroups" :key="group.category" class="tag-group">
|
||||
<n-text depth="3" class="tag-group-label">{{ group.label }}</n-text>
|
||||
<n-flex>
|
||||
<n-tag
|
||||
v-for="tag in group.tags"
|
||||
:closable="tag.checked"
|
||||
@close="chooseTag(tag)"
|
||||
@click="chooseTag(tag)"
|
||||
:key="tag.id"
|
||||
:type="tag.checked ? 'success' : 'default'"
|
||||
class="tag-chip"
|
||||
>
|
||||
{{ tag.name }}
|
||||
</n-tag>
|
||||
</n-flex>
|
||||
</div>
|
||||
</div>
|
||||
</n-collapse-transition>
|
||||
<n-data-table :bordered="false" :data="problems" :columns="columns" :row-props="rowProps" />
|
||||
</n-flex>
|
||||
@@ -330,6 +352,28 @@ function rowProps(row: ProblemRow) {
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.tag-groups {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.tag-group {
|
||||
display: grid;
|
||||
grid-template-columns: 48px minmax(0, 1fr);
|
||||
align-items: start;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.tag-group-label {
|
||||
font-size: 13px;
|
||||
line-height: 28px;
|
||||
}
|
||||
|
||||
.tag-chip {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.problem-list-toolbar {
|
||||
grid-template-columns: minmax(0, 1fr);
|
||||
|
||||
Reference in new issue
Block a user